37414
Goto Top

Druckername per VBA-Script über externe Textdatei auswählen

Hallo,

vor ein paar Tagen hatte ich mit Eurer Hilfe den unten eingesetzten Code genutzt, um automatisch 2 Textzeilen aus einer extern auf dem Server abgelegten Textdatei (daten.txt) auszulesen und diesen in ein Dokument einzusetzen. Hierbei sucht der Code nach den Namen der jeweiligen User und setzt den passenden Text ein.

Nun würde ich dieses Script gerne so erweitern, dass in dieser Textdatei "daten.txt" auch die zu den Mitarbeitern passenden Druckernamen mit ausgelesen werden können. Es müßten also 2 weitere Strings dort eingesetzt werden können (a: Drucker zum drucken des aktuellen Dokumentes // b: Standarddrucker wieder aktivieren).

Das neue Script soll dann im Einzelnen folgendes machen:

1) In der Datei "daten.txt" nach dem angemeldeten User suchen (wie es ja auch bereits unten in dem Code für die Text-Einsätze gemacht wird)

2) Dann soll der dritte String (also der jew. Druckername) gewählt werden und das Dokument dann darauf ausgedruckt werden

3) Am Ende soll wieder der Standarddrucker gewählt werden. Am besten (sichersten) wäre es, wenn dieser vielleicht in der Textdatei "daten.txt" als vierter String eingesetzt werden könnte.

Zur Info:
Mit dem bisher im unten eingesetzten Code verwendeten "strPrintername = "MV_" & strUsername & "_Blanko"" funktioniert es nicht, da die jeweiligen Drucker der Mitarbeiter unterschiedliche Namen haben.

Ich wollte dazu den hier eingesetzten Code verwenden... habe das aber nicht hinbekommen, da ich u.a. nicht sicher war, wo ich was einsetzen muss.
Wahrscheinlich muss in Zeile 4 des Codes der Zusatz "strText3 As String" und "strText4 As String" zusätzlich eingetragen werden.
Weiterhin in der Textdatei "daten.txt" die Angaben der beiden Drucker in dieser Art: --> User-Name;i. A.;Dienstbezeichnung;Druckername1;Standarddrucker
Am Ende vermute ich mal, dass für die Drucker eine Variable eingesetzt werden muss...

Wäre schön, wenn Ihr mir hierbei helfen könntet.

Danke und Gruss,
imebro

Hier der Code aus dem vorherigen Thread:

Sub Druck()
'  
    Dim img As InlineShape, posImage As Range, posAbteilung As Range, posImAuftrag As Range
    Dim objShell As Object, fso As Object, regex As Object, matches, strText1 As String, strText2 As String
    
    'Pfad zur Textdatei mit den Namen und Dienstbezeichnungen der Mitarbeiter der MV:  
    Const FILEPATH = "S:\ARCHIV\Mittelvergabe\Daten_MV\daten.txt"  
    
    'Objekte:  
    Set objShell = CreateObject("Wscript.Shell")  
    Set fso = CreateObject("Scripting.FileSystemObject")  
    Set regex = CreateObject("vbscript.regexp")  
    
    ' Zuweisung der einzelnen Pfade:  
    strUsername = objShell.ExpandEnvironmentStrings("%username%")  
    strUserprofile = objShell.ExpandEnvironmentStrings("%userprofile%")  
    
    'Druckernamen  
    strPrintername = "MV_" & strUsername & "_Blanko"  
    
    'Regex Settings:  
    regex.Global = False: regex.IgnoreCase = True: regex.MultiLine = True
    
    'Regex Pattern für Zeilen - Hier wird der Inhalt der Textdatei "daten.txt" ausgelesen:  
    regex.Pattern = "^" & strUsername & ";(.*);(.*)"  
    
    'Regex auf Inhalt der Textdatei anwenden (Usernamen suchen):  
    Set matches = regex.Execute(fso.OpenTextFile(FILEPATH, 1).ReadAll())
    
    'Wurde ein Treffer gefunden setze die Variablen:  
    If matches.Count > 0 Then
        strText1 = matches(0).Submatches(0)
        strText2 = matches(0).Submatches(1)
    Else    'es wurde kein passender User gefunden, (Werte der Variablen auf Defaultwerte setzen)  
        strText1 = ""  
        strText2 = ""  
    End If
    
    
    'Beginn einsetzen von "i. A." und der passenden Dienstbezeichnung des Mitarbeiters:  
    Selection.GoTo wdGoToPage, wdGoToFirst
    With ActiveDocument.Content.Find
        .Text = "Mit freundlichen Grüßen"  
        .Forward = True
        .Wrap = wdFindContinue
        .MatchWildcards = True
        .Execute
        If .Found Then
            'Erstellen der benötigten Anzahl Absätze  
            For i = 1 To 7
                .Parent.InsertParagraphAfter
            Next
            ' setze die Position 5 Absätze hinter das "Mit freundlichen Grüßen"  
            Set posImAuftrag = .Parent.GoTo(wdGoToLine, wdGoToNext, 5)
            With posImAuftrag
                .End = .Paragraphs(1).Range.End
                .Font.Name = Arial
                .Font.Size = 11
                .Text = strText1   'einsetzen des 2. Textteils aus der Datei "daten.txt"  
            End With
            ' Setze die Position einen Absatz weiter als die "posImAuftrag" Zeile  
            Set posAbteilung = posImAuftrag.GoTo(wdGoToLine, wdGoToNext, 1)
            With posAbteilung
                .End = .Paragraphs(1).Range.End
                .Font.Name = Arial
                .Font.Size = 9
                .Text = strText2   'einsetzen des 3. Textteils aus der Datei "daten.txt"  
            End With
        End If
    End With
    
    Set objShell = Nothing
    Set fso = Nothing
    Set regex = Nothing
 
End Sub

Content-Key: 261388

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

Ausgedruckt am: 28.03.2024 um 19:03 Uhr

Mitglied: colinardo
colinardo 28.01.2015 aktualisiert um 12:02:00 Uhr
Goto Top
Hello again imebro,
ich würde den Standarddrucker nicht in der Textdatei hinterlegen (falls du das wider erwarten doch willst kannst du dir jetzt abschauen wie der Regex-Pattern dazu angepasst werden muss), sondern direkt aus Word ermitteln. Die zusätzliche Spalte für den persönlichen Drucker für das Dokument habe ich dir hier ergänzt.
Kommentare findest du im Code.
Deine Druckroutine musst du noch ergänzen (s.Kommentare im Code)
Sub Druck()
    Dim img As InlineShape, posImage As Range, posAbteilung As Range, posImAuftrag As Range
    Dim objShell As Object, fso As Object, regex As Object, matches, strText1 As String, strText2 As String, strPrinter As String, strPrinterDefault As String
    
    'Pfad zur Textdatei mit den Namen und Dienstbezeichnungen der Mitarbeiter der MV:  
    Const FILEPATH = "S:\ARCHIV\Mittelvergabe\Daten_MV\daten.txt"  
    
    'Objekte:  
    Set objShell = CreateObject("Wscript.Shell")  
    Set fso = CreateObject("Scripting.FileSystemObject")  
    Set regex = CreateObject("vbscript.regexp")  
    
    ' Zuweisung der einzelnen Pfade:  
    strUsername = objShell.ExpandEnvironmentStrings("%username%")  
    strUserprofile = objShell.ExpandEnvironmentStrings("%userprofile%")  
    
    'aktuellen Drucker ermitteln  
    strPrinterDefault = ActivePrinter
    
    'Regex Settings:  
    regex.Global = False: regex.IgnoreCase = True: regex.MultiLine = True
    
    'Regex Pattern für Zeilen - Hier wird der Inhalt der Textdatei "daten.txt" ausgelesen:  
    regex.Pattern = "^" & strUsername & ";(.*);(.*);(.*)"  
    
    'Regex auf Inhalt der Textdatei anwenden (Usernamen suchen):  
    Set matches = regex.Execute(fso.OpenTextFile(FILEPATH, 1).ReadAll())
    
    'Wurde ein Treffer gefunden setze die Variablen:  
    If matches.Count > 0 Then
    	' i.A.  
        strText1 = matches(0).Submatches(0)
        ' Dienstbezeichnung  
        strText2 = matches(0).Submatches(1)
        ' Zieldrucker  
        strPrinter = matches(0).Submatches(2)
    Else    'es wurde kein passender User gefunden, (Werte der Variablen auf Defaultwerte setzen)  
        strText1 = ""  
        strText2 = ""  
        strPrinter = strPrinterDefault
    End If
    
    
    'Beginn einsetzen von "i. A." und der passenden Dienstbezeichnung des Mitarbeiters:  
    Selection.GoTo wdGoToPage, wdGoToFirst
    With ActiveDocument.Content.Find
        .Text = "Mit freundlichen Grüßen"  
        .Forward = True
        .Wrap = wdFindContinue
        .MatchWildcards = True
        .Execute
        If .Found Then
            'Erstellen der benötigten Anzahl Absätze  
            For i = 1 To 7
                .Parent.InsertParagraphAfter
            Next
            ' setze die Position 5 Absätze hinter das "Mit freundlichen Grüßen"  
            Set posImAuftrag = .Parent.GoTo(wdGoToLine, wdGoToNext, 5)
            With posImAuftrag
                .End = .Paragraphs(1).Range.End
                .Font.Name = Arial
                .Font.Size = 11
                .Text = strText1   'einsetzen des 2. Textteils aus der Datei "daten.txt"  
            End With
            ' Setze die Position einen Absatz weiter als die "posImAuftrag" Zeile  
            Set posAbteilung = posImAuftrag.GoTo(wdGoToLine, wdGoToNext, 1)
            With posAbteilung
                .End = .Paragraphs(1).Range.End
                .Font.Name = Arial
                .Font.Size = 9
                .Text = strText2   'einsetzen des 3. Textteils aus der Datei "daten.txt"  
            End With
        End If
    End With
    
    'Ziel-Drucker für das Dokument setzen  
    ActivePrinter = strPrinter
    
    ' ===============================  
    ' Hier deine Druckroutine aufrufen  
    ' .....  
    ' ===============================  
    
    'Alten Standarddrucker wieder setzen  
    ActivePrinter = strPrinterDefault
    
    Set objShell = Nothing
    Set fso = Nothing
    Set regex = Nothing
End Sub
Es sei dir nochmal das Regular Expressions Tutorial empfohlen damit du Regular Expression auch verstehst face-wink

Grüße Uwe

p.s. so langsam ist mal eine Spende für die Beteiligten angesagt !
Mitglied: 37414
37414 28.01.2015 aktualisiert um 13:32:06 Uhr
Goto Top
Danke Dir Uwe...

sicher hast Du Recht mit der Spende. Werde meinen AG mal darauf ansprechen... schließlich ist das ja für seine Mitarbeiter face-wink

Bezüglich des Codes:

Das Auswählen der Texte "i. A." und "Dienstbezeichnung" mache ich ja über den bereits vorhandenen Code.
Dieses Script hier soll quasi davon getrennt sein und NUR den Druckbefehl geben und dazu den jeweiligen User-Drucker aus der Textdatei "daten.txt" nehmen.

Ich nehme an, dass ich dazu lediglich die nicht benötigten Zeilen Deines heutigen Codes heraus löschen müßte.

Zur Druckroutine:

Diese sieht zur Zeit so aus:

    ActivePrinter = "\\dasfile\Müller_Brief"  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ActivePrinter = "\\dasfile\Müller_Blanko"  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0

Das Dokument wird zuerst auf Briefpapier und danach noch auf Blankopapier gedruckt... Der Blanko-Drucker soll dann wieder der Standarddrucker sein.
Soll ich also diesen Inhalt ab Zeile 81 aufnehmen - ohne die jeweiligen Angaben bei "ActivePrinter"?

Die Datei "Daten.txt" habe ich nun einfach ergänzt um ";Drucker_des_Users" direkt hinter der Dienstbezeichnung.

--> Beispiel: "Max Müller;i. A. Max Müller;Mittelvergabe;Müller_Brief"

Ich füge hier mal den Code so ein, wie ich es mir jetzt denke:

Sub Druck()
    Dim img As InlineShape, posImage As Range, posAbteilung As Range, posImAuftrag As Range
    Dim objShell As Object, fso As Object, regex As Object, matches, strText1 As String, strText2 As String, 

strPrinter As String, strPrinterDefault As String
    
    'Pfad zur Textdatei mit den Namen und Dienstbezeichnungen der Mitarbeiter der MV:  
    Const FILEPATH = "S:\ARCHIV\Mittelvergabe\Daten_MV\daten.txt"  
    
    'Objekte:  
    Set objShell = CreateObject("Wscript.Shell")  
    Set fso = CreateObject("Scripting.FileSystemObject")  
    Set regex = CreateObject("vbscript.regexp")  
    
    ' Zuweisung der einzelnen Pfade:  
    strUsername = objShell.ExpandEnvironmentStrings("%username%")  
    strUserprofile = objShell.ExpandEnvironmentStrings("%userprofile%")  
    
    'aktuellen Drucker ermitteln  
    strPrinterDefault = ActivePrinter
    
    'Regex Settings:  
    regex.Global = False: regex.IgnoreCase = True: regex.MultiLine = True
    
    'Regex Pattern für Zeilen - Hier wird der Inhalt der Textdatei "daten.txt" ausgelesen:  
    regex.Pattern = "^" & strUsername & ";(.*);(.*);(.*)"  
    
    'Regex auf Inhalt der Textdatei anwenden (Usernamen suchen):  
    Set matches = regex.Execute(fso.OpenTextFile(FILEPATH, 1).ReadAll())
    
    'Wurde ein Treffer gefunden setze die Variablen:  
    If matches.Count > 0 Then
    	' i.A.  
        strText1 = matches(0).Submatches(0)
        ' Dienstbezeichnung  
        strText2 = matches(0).Submatches(1)
        ' Zieldrucker  
        strPrinter = matches(0).Submatches(2)
    Else    'es wurde kein passender User gefunden, (Werte der Variablen auf Defaultwerte setzen)  
        strText1 = ""  
        strText2 = ""  
        strPrinter = strPrinterDefault
    End If
    
      
    'Ziel-Drucker für das Dokument setzen  
    ActivePrinter = strPrinter
    
    ' =====================================================================  
    ' Druckroutine aufrufen:  
    '     
	Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ' =====================================================================  
    
    'Alten Standarddrucker wieder setzen  
    ActivePrinter = strPrinterDefault
    
    Set objShell = Nothing
    Set fso = Nothing
    Set regex = Nothing
End Sub

Danke und Gruss,
imebro
Mitglied: colinardo
colinardo 28.01.2015 aktualisiert um 13:31:32 Uhr
Goto Top
Soll ich also diesen Inhalt ab Zeile 81 aufnehmen?
jup, so war's gedacht ...
Mitglied: 37414
37414 28.01.2015 aktualisiert um 13:42:00 Uhr
Goto Top
Ok...

ich hatte diesen Bereich gerade noch abgeändert, da das Dokument zuerst auf Briefpapier (Drucker "Müller_Brief") und danach noch auf Blankopapier (Drucker "Müller_Blanko") gedruckt werden soll.

Muss ich dann nur die beiden Zeilen mit "ActivePrinter" löschen oder dort eingeben:

"ActivePrinter = strPrinter" für den ersten
und "ActivePrinter = strPrinterDefault" für den zweiten Druckvorgang

Also quasi so:

    ActivePrinter = "strPrinter"  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ActivePrinter = "strPrinterDefault"  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0

Dann die Zeilen 47 und 59 aus meinem weiter oben eingefügten Code löschen...

LG
imebro
Mitglied: colinardo
Lösung colinardo 28.01.2015, aktualisiert am 29.01.2015 um 13:52:15 Uhr
Goto Top
Warum schaust du nicht einfach mal nach was das ActivePrinter bedeutet, dann verstehst du es auch und musst nicht jede Kleinigkeit nachfragen.
ActivePrinter = "Druckername"
setzt den aktiven Drucker und
ActivePrinter = strPrinterDefault
setzt ihn auf den Wert zurück den er zu beginn hatte. Nicht schwer oder ?

wie man Variablen verwendet solltest du doch inzwischen wissen, denn dein Konstrukt
"strPrinter" ist so keine Variable sondern ein String...
wenn dann verwendet man die Variable natürlich so !!
ActivePrinter = strPrinter
Mitglied: 37414
37414 28.01.2015 aktualisiert um 15:34:37 Uhr
Goto Top
Ja, da hast Du natürlich Recht face-wink

Hatte auch nur vergessen, die "" zu entfernen.
In meinem Test-Script hatte ich die schon raus.

Habe es jetzt nochmal etwas anders gelöst, damit nicht noch die Teile aus dem vorherigen Script (also mit dem "i.A." und "Dienstbezeichnung") mit drin stehen.

Habe jetzt einfach eine neue Textdatei erstellt (druck.txt).
In der steht nur der Username und der dazu passende Drucker

--> Max-Müller;Max-Müller_Brief

Dann habe ich die Teile aus dem Script entfernt, die dort nicht mehr benötigt werden.
Dadurch wird auch der Code kürzer und übersichtlicher face-smile

Hier jetzt der Code dieses Scriptes:

Sub Druck()
'  
    Dim img As InlineShape, posImage As Range, posAbteilung As Range, posImAuftrag As Range
    Dim objShell As Object, fso As Object, regex As Object, matches, strPrinter As String, strPrinterDefault As 

String
    
    'Pfad zur Textdatei mit den Namen und Dienstbezeichnungen der Mitarbeiter der MV:  
    Const FILEPATH = "S:\ARCHIV\Mittelvergabe\Daten_MV\druck.txt"  
    
    'Objekte:  
    Set objShell = CreateObject("Wscript.Shell")  
    Set fso = CreateObject("Scripting.FileSystemObject")  
    Set regex = CreateObject("vbscript.regexp")  
    
    ' Zuweisung der einzelnen Pfade:  
    strUsername = objShell.ExpandEnvironmentStrings("%username%")  
    strUserprofile = objShell.ExpandEnvironmentStrings("%userprofile%")  
    
    'aktuellen Drucker ermitteln  
    strPrinterDefault = ActivePrinter
    
    'Regex Settings:  
    regex.Global = False: regex.IgnoreCase = True: regex.MultiLine = True
    
    'Regex Pattern für Zeilen - Hier wird der Inhalt der Textdatei "druck.txt" ausgelesen:  
    regex.Pattern = "^" & strUsername & ";(.*)"  
    
    'Regex auf Inhalt der Textdatei anwenden (Usernamen suchen):  
    Set matches = regex.Execute(fso.OpenTextFile(FILEPATH, 1).ReadAll())
    
    'Wurde ein Treffer gefunden setze die Variablen:  
    If matches.Count > 0 Then
    	'Zieldrucker  
        strPrinter = matches(0).Submatches(0)
    Else    'es wurde kein passender User gefunden, (Werte der Variablen auf Defaultwerte setzen)  
        strPrinter = strPrinterDefault
    End If    

    
    ' =====================================================================  
    ' Druckroutine aufrufen:  
    '     
    ActivePrinter = strPrinter
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ActivePrinter = strPrinterDefault
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ' =====================================================================  
    
    
    Set objShell = Nothing
    Set fso = Nothing
    Set regex = Nothing
End Sub

Wichtig sind die Einträge in Zeile 4 und 34-37.
Hoffe dass diese so richtig sind face-smile

LG
imebro

UPDATE:

Habe eben mal dieses Script getestet.
Es gab gleich einen Laufzeitfehler zurück und beim Debuggen wurde folgende Zeile markiert:

ActivePrinter = strPrinter

Also direkt die 1. Zeile in der Druckroutine.
Woran könnte das liegen?

LG
imebro

UPDATE 2:

Wäre es ggf. möglich, dass ich den Eintrag des Zieldruckers in der Textdatei "druck.txt" anders machen muss?

Dort steht er ja so:
Max-Müller;Max-Müller_Brief

Der Drucker befindet sich aber im Netzwerk.
Der korrekte Pfad ist: "\\DASFILE\Max-Müller_Brief"

Wenn ich ihn in der "druck.txt" genau so angebe, funktioniert es jedenfalls auch nicht...

LG
imebro
Mitglied: 114757
114757 28.01.2015 aktualisiert um 15:44:16 Uhr
Goto Top
Woran könnte das liegen?
Falscher Druckername wurde angegeben ...
http://support.microsoft.com/kb/209722
https://msdn.microsoft.com/de-de/library/office/ff821995%28v=office.15%2 ...

Bei Netzwerkdruckern muss das anders lauten
Application.ActivePrinter = "HP LaserJet IIISi on \\printers\laser"

je nach System auch auf Deutsch ... kannst du die ja anzeigen lassen indem du den Drucker als Standard setzt und dann via Msgbox den Namen ausgeben lässt.

Gruß jodel
Mitglied: 37414
37414 28.01.2015 aktualisiert um 15:47:45 Uhr
Goto Top
Danke Dir...

Aber in meinem bisherigen Script, in dem der Drucker mit seinem tatsächlichen Namen angegeben wird, funktioniert es ja mit

"\\DASFILE\Max-Müller_Brief"

Hier mal der Code des funktionierenden Druck-Makros:

Sub Druck()
'  
    ActivePrinter = "\\dasfile\Max-Müller_Brief"  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ActivePrinter = "\\dasfile\Max-Müller_Blanko"  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub

Hierbei war vor dem Druck der Blanko-Drucker der Standarddrucker.
Dieser soll am Ende auch wieder Standarddrucker sein... und mit diesem Code ist das auch so.

Dabei ist nur das Problem, dass der Druckername jeweils im Script angegeben werden muss.
Die neue Variante sollte das ja verhindern, indem der jeweilige Drucker automatisch über eine Textdatei "druck.txt" dem jeweiligen User zugeordnet wird.

Ich hatte vermutet, dass das Problem in der Textdatei "druck.txt" liegt, aus der der jeweilige User und der jeweilige Drucker des Users herausgesucht werden.
Dort ist der Eintrag im Moment so angegeben:

Max-Müller;Max-Müller_Brief
Lutz-Schneider;Lutz-Schneider_Brief
...

LG
imebro
Mitglied: 114757
Lösung 114757 28.01.2015, aktualisiert am 29.01.2015 um 13:51:38 Uhr
Goto Top
dann sind die Umlaute dran Schuld, weil es aus einer Textdatei ausgelesen wird.
Wenn du die Zeile so anpasst müssten diese richtig interpretiert werden, da ansonsten nur als ASCII ausgelesen wird:
Set matches = regex.Execute(fso.OpenTextFile(FILEPATH, 1,false,2).ReadAll())
Mitglied: 37414
37414 28.01.2015 aktualisiert um 15:56:29 Uhr
Goto Top
...beim Test mit Deiner Code-Zeile wird genau diese beim debuggen markiert mit folgender Fehlermeldung:

"Ungültiger Prozeduraufruf oder ungültiges Argument"

LG
imebro
Mitglied: 114757
114757 28.01.2015 um 15:59:22 Uhr
Goto Top
Zitat von @37414:

...beim Test mit Deiner Code-Zeile wird genau diese beim debuggen markiert mit folgender Fehlermeldung:

"Ungültiger Prozeduraufruf oder ungültiges Argument"

Die Parameter stimmen alle, siehe:
https://msdn.microsoft.com/en-us/library/aa265347(v=vs.60).aspx
Mitglied: 114757
114757 28.01.2015 aktualisiert um 16:05:39 Uhr
Goto Top
eventuell sind ja Leerzeichen am Ende deines Druckernamens, oder Zeilenumbrüche. Dann musst du diese entweder mit trim() entfernen oder eben aus der Textdatei oder den Pattern auch mal so schreiben:
regex.Pattern = "^" & strUsername & ";(.*)$"   
Mitglied: 37414
37414 28.01.2015 aktualisiert um 16:10:23 Uhr
Goto Top
hmmm... verstehe ich jetzt gar nicht mehr.

Das Beispiel mit Max-Müller ist auch nur ein Beispiel.
In Wirklichkeit ist in dem Namen, mit dem ich teste, gar kein Umlaut drin...

Merkwürdig ist, dass mein jetziges Script (also das, wo die Druckernamen mit Pfad drin stehen) ja perfekt funktioniert.
Nur klappt es nicht, wenn ich es über das auslesen über die Textdatei mache.

Daher kann der Fehler nur in diesem Code sein, wo Username und Drucker ausgelesen werden oder in meiner Textdatei "druck.txt".
Aber alle Dateien stehen ja jetzt hier in diesem Thread drin und ich kann auch keinen Fehler finden oder noch irgendwo einen vermuten.

Hmmm... seltsam face-sad

LG
imebro
Mitglied: 37414
37414 28.01.2015 aktualisiert um 16:11:11 Uhr
Goto Top
Das mit dem $-Zeichen zusätzlich hat auch nichts gebracht.

Immer wieder erscheint die Fehlermeldung und beim Debuggen wird die Zeile

"ActivePrinter = strPrinter"

gelb markiert.

LG
imebro
Mitglied: 114757
114757 28.01.2015 aktualisiert um 16:18:26 Uhr
Goto Top
Was steht im gelben Tooltip wenn du mit der Maus über strPrinter fährst, während die Zeile gelb markiert ist ?
Schon mal was von Debugging gehört face-wink
Mitglied: 37414
37414 28.01.2015 aktualisiert um 16:28:16 Uhr
Goto Top
Yes face-smile

Da steht "strPrinter = "Max-Müller_Brief"

Also im Grunde das, was auch der Wahrheit entspricht.
Vielleicht sollte ich in der Textdatei "druck.txt" mal die Klammern mit eintragen... vielleicht klappts dann?

LG
imebro

UPDATE:

Hat nicht geklappt... aber beim Tooltip werden dann jetzt je 2 Klammern angezeigt. face-smile
Also dürfte ohne Klammern richtig gewesen sein.

Also dann noch immer keine Lösung.

Aber... morgen dann mehr - muss jetzt noch in eine Besprechung.

Danke bis dahin.

LG
imebro
Mitglied: 116301
116301 28.01.2015 aktualisiert um 17:57:02 Uhr
Goto Top
Hallo imebro!

hmmm... verstehe ich jetzt gar nicht mehr.
Das Beispiel mit Max-Müller ist auch nur ein Beispiel.
In Wirklichkeit ist in dem Namen, mit dem ich teste, gar kein Umlaut drin...

Hier mal der Code des funktionierenden Druck-Makros:
ActivePrinter = "\\dasfile\Max-Müller_Brief"   

Dort ist der Eintrag im Moment so angegeben:
Max-Müller;Max-Müller_Brief
Lutz-Schneider;Lutz-Schneider_Brief
Vielleicht klappts dann ja so:
ActivePrinter = "\\dasfile\" & strPrinter  

Grüße Dieter
Mitglied: 37414
37414 29.01.2015 um 08:44:50 Uhr
Goto Top
Hallo Dieter,

yes... das war´s face-wink

Habe jetzt den Code-Teil, der für den eigentlichen Druckvorgang zuständig ist, so abgeändert:

' Druckroutine aufrufen:  
    '  
    ActivePrinter = "\\dasfile\" & strPrinter  
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
    ActivePrinter = strPrinterDefault
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _  
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
        Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
        PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0

Zunächst ist unser Blanko-Drucker der Standarddrucker. Das wird ja weiter oben im Code schon festgestellt.
Dann wird in der Druckroutine zunächst auf dem Brief-Drucker ausgedruckt (strPrinter). Dieser wird ja aus der Textdatei "druck.txt" ausgelesen.
Anschließend wird dann wiederum auf dem Standarddrucker (strPrinterDefault) ausgedruckt... also wieder auf dem Blanko-Drucker.
Und dieser soll am Ende auch wieder bzw. immer noch der Standarddrucker bleiben.

Im Grunde läuft es so korrekt!

Was ich nur noch nicht so ganz verstehe, ist, wieso ich den ersten Ausdruck auf dem Brief-Drucker über den Code --> "\\dasfile\" & strPrinter <--- angeben muss und nachher den Standarddrucker nur über "strPrinterDefault"...
Ich hatte ja gestern schon einen Test gemacht, bei dem ich in der Textdatei "druck.txt" den Zusatz "\\dasfile\" mit eingesetzt hatte. Bei diesem Versuch hatte ich dann im Code auch nur "ActivePrinter = strPrinter" angegeben. Das hatte aber auch nicht funkitoniert. Finde ich irgendwie seltsam...

So wie es jetzt funktioniert, wäre es für mich logisch, wenn in der Textdatei "druck.txt" die Zeilen so aussehen würden:

Max-Müller;"\\dasfile\Max-Müller_Brief"  
Lutz-Schneider;"\\dasfile\Lutz-Schneider_Brief"  

...und nicht so, wie es jetzt ist:

Max-Müller;Max-Müller_Brief
Lutz-Schneider;Lutz-Schneider_Brief

Aber ist im Grunde ja auch wurscht face-wink Es funktioniert ja so... würde es halt nur gerne auch verstehen face-smile

Danke und Gruss,
imebro
Mitglied: colinardo
Lösung colinardo 29.01.2015 aktualisiert um 13:51:52 Uhr
Goto Top
Lutz-Schneider;"\\dasfile\Lutz-Schneider_Brief"
Lass die Anführungszeichen weg .... dann geht das auch damit face-wink , denn diese würden in diesem Fall sonst als Teil des Namens interpretiert, weil der Regex-Pattern eben so angelegt ist.

Grüße Uwe
Mitglied: 37414
37414 29.01.2015 um 09:15:36 Uhr
Goto Top
...ach mensch.... diese verdammten Anführungszeichen...
Manchmal kann alles sooo einfach sein face-wink

Danke Dir Uwe!

Hat funktioniert und jetzt ist das Ganze auch logisch für mich.
Habe den Code in der Druckroutine des Makros jetzt wieder so abgeändert, wie anfangs:

ActivePrinter = strPrinter

und in der Datei "druck.txt" jetzt so:

Max-Müller;\\dasfile\Max-Müller_Brief 
Lutz-Schneider;\\dasfile\Lutz-Schneider_Brief

So klappt´s.

Danke nochmals und @ Uwe:
...werde meinen Chef auf ne Spende ansprechen face-smile

LG
imebro
Mitglied: 37414
37414 30.01.2015 um 08:46:54 Uhr
Goto Top
Habe den Beitrag gestern zwar als GELÖST markiert, aber es ist kaum zu fassen...

Nun habe ich den Code kopiert und auf dem ersten anderen Rechner getestet - und - was passiert?
Wieder wird die Zeile "ActivePrinter = strPrinter" im VBA-Editor mit Laufzeitfehler angemeckert face-sad

Das kann ich nun überhaupt nicht begreifen, da es ja bei mir nun so funktioniert.
Auch in der Textdatei "druck.txt" sind alle Einträge genauso, wie bei mir.

Ich kann absolut keinen Fehler finden...

Falls noch jemand von Euch ne Idee hat, dann gerne... aber ich habe jetzt eher keine Lust mehr und habe im Moment die "alte" Druckroutine wieder an diesem Rechner eingesetzt, wo ich den genauen Druckernamen angeben muss und der diesen nicht aus der Textdatei "druck.txt" ausliest.

LG
imebro
Mitglied: colinardo
colinardo 30.01.2015 aktualisiert um 14:52:46 Uhr
Goto Top
Wie gesagt das liegt zu 99% daran das deine Druckernamen nicht exakt stimmen, da reicht schon ein hinein gerutschtes Leerzeichen am Ende aus. Das lässt sich aber mit einem Trim(strPrinter) umgehen, welches führende oder nachfolgende Leerzeichen entfernt.

Eine andere Methode den Standarddrucker zu setzen ist es via WMI zu machen.

Methode zum Auslesen des aktuellen Standarddruckers via WMI:
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")  
Set colPrinters =  objWMIService.ExecQuery("Select * from Win32_Printer Where Default = True")  
For Each objPrinter in colInstalledPrinters
    strPrinterDefault = objPrinter.Name
Next
Methode um den Standarddrucker zurückzusetzen (oder einen anderen Drucker als Default zu deklarieren)
strPrinterDefault = Replace(strPrinterDefault,"\","\\")  
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")  
'Alten Standarddrucker wieder setzen  
Set colPrinters =  objWMIService.ExecQuery("Select * from Win32_Printer Where Name = '" & strPrinterDefault & "'")  
For Each objPrinter in colPrinters
    objPrinter.SetDefaultPrinter()
Next

Das nutzt dir aber alles nichts wenn deine Namen nicht absolut korrekt sind.

Und überhaupt, was seit Ihr für eine Firma die einen Programmierneuling an solch eine Sache heran lassen ??

Ich empfehle dir dringend dich mal eingehend einzulesen und vor allem das Debugging im VBA-Editor (Breakpoints, etc) zu beherrschen. Programmieren besteht nun mal aus vielen Variablen,da zeigt es es sich meist erst in der Praxis wo es zu Problemen kommt. Office 2000 auf einem Terminalserver ist ja auch schon ein wenig irre face-wink.

back-to-topVBA/VBS/WSH/Office Developer Referenzen

Ohne mehr Infos zu den aktuellen Werten der Variablen auf der betreffenden Station und Umgebung wird das hier wieder zu einer ellenlangen Diskussion, und dir hier VBA von Grund auf beizubringen ist eigentlich nicht unsere Aufgabe, sorry...

Grüße Uwe
Mitglied: 37414
37414 30.01.2015 um 12:19:28 Uhr
Goto Top
Hallo Uwe,

ja, da hast Du Recht.
Es fing eigentlich mit einem kleinen Makro an... und dann kamen die Kollegen und wollten es immer komplexer haben.
Dadurch hat sich das so ergeben face-wink

Bezüglich dem "Trim(strPrinter)":

Da hatte ich doch schon den folgenden Tipp erhalten, mit dem $-Zeichen zusätzlich:

regex.Pattern = "^" & strUsername & ";(.*)$"   

Meintest Du mit "Leerzeichen am Ende..." in meiner Textdatei "druck.txt"?
Die habe ich überprüft - und da sind keine Leerzeichen drin.
Die Namen stimmen zu 100% überein.

Aber... könnte es auch mit Groß-/Kleinschreibung zusammenhängen?
Bei manchen Kollegen wird nämlich der Server "\\dasfile" geschrieben und bei anderen "\\DASFILE".

Wo müßte ich das "Trim(strPrinter)" denn im Code einsetzen?

Danke und Gruss,
imebro
Mitglied: colinardo
colinardo 30.01.2015 aktualisiert um 12:32:44 Uhr
Goto Top
Zitat von @37414:
Da hatte ich doch schon den folgenden Tipp erhalten, mit dem $-Zeichen zusätzlich:
Das hast du aber falsch Interpretiert, das Dollarzeichen bezeichnet das Ende einer Zeile und soll verhindern das Zeilenumbrüche mit in die Variable wandern, das tun sie aber trotzdem nicht.
Meintest Du mit "Leerzeichen am Ende..." in meiner Textdatei "druck.txt"?
Ich meine jegliche Leerezeichen die vor und hinter den Semikolons stehen, denn diese sind ja die Trenner der Spalten.
Ich könnte das Regex-Pattern jetzt natürlich auch noch so erweitern das das alles egal wäre. Aber wenn du weißt worauf es ankommt ist das ja nicht nötig.
Die habe ich überprüft - und da sind keine Leerzeichen drin.
Die Namen stimmen zu 100% überein.
Aber... könnte es auch mit Groß-/Kleinschreibung zusammenhängen?
In einem Test tut es das hier nicht.
Wo müßte ich das "Trim(strPrinter)" denn im Code einsetzen?
das kannst du schon ganz zu Beginn hier machen:
strPrinter = Trim(matches(0).Submatches(0))
Grüße Uwe
Mitglied: 37414
37414 30.01.2015 aktualisiert um 14:21:51 Uhr
Goto Top
...ich glaube, ich lasse es jetzt.

Habe wieder die alte Druckroutine eingesetzt, wo die Drucker mit ihren tatsächlichen Namen direkt angesprochen werden.

Mit dem Zusatz "Trim" gab es den gleichen Laufzeitfehler im VBA-Editor, wie vorher auch.
Übrigens ist es immer der Laufzeitfehler 5216, der aber in der Script-Hilfedatei nicht aufgeführt ist.

Microsoft sagt folgendes zu dem Fehler:
Hinweis: Wenn Sie dieses Makro ausführen, und geben Sie einen Drucker, der nicht installiert ist, wird die folgende Fehlermeldung angezeigt:
Laufzeitfehler '5216': Druckerfehler ist aufgetreten.

Eine Office-Seite sagt dazu:
5216 = Den letzten Teile eines mit Semikolon getrennten Strings ermitteln

--> Allerdings ist der Drucker ja korrekt und es funktioniert damit ja auch über die normale Druckroutine!

Habe dann zusätzlich in der Textdatei "druck.txt" mal noch testweise das "DASFILE" in groß geschrieben... aber der Fehler bleibt.

Wurmt mich einfach...
Aber ich will Dich / Euch jetzt damit auch nicht länger weiter quälen face-wink

Danke und Gruss,
imebro
Mitglied: 37414
37414 30.01.2015 um 14:32:20 Uhr
Goto Top
Glaube ich hab´s face-wink

Habe im VBA-Editor beim debuggen mal den Mauszeiger auf "ActivePrinter" gesetzt.
Dabei viel mir auf, dass dann dort folgendes stand:

\\dasfile\Maier_Blanko on NE14

Nun habe ich dieses ominöse "NE14" einfach mal in der Textdatei "druck.txt" noch hinter den Druckernamen eingegeben... und zwar so:

Lisa-Meier;\\dasfile\Maier_Blanko on NE14

Und anschließend lief der Druckvorgang durch. face-smile

Seltsam finde ich nur, dass es bei mir auch ohne das "NE14" (oder einen ähnlichen Ausdruck) funktioniert...

LG
imebro
Mitglied: 114757
114757 30.01.2015 aktualisiert um 14:40:10 Uhr
Goto Top
Nun habe ich dieses ominöse "NE14" einfach mal in der Textdatei "druck.txt" noch hinter den Druckernamen eingegeben... und zwar so:
hab ich doch schon ganz zu Beginn geschrieben ... aber wer nicht hören will muss fühlen :-P

Seltsam finde ich nur, dass es bei mir auch ohne das "NE14" (oder einen ähnlichen Ausdruck) funktioniert...
Du sagst ja auch kein Wort wie sich dein System vom anderen unterscheidet (Server/Client/ etc. pp)
Mitglied: 37414
37414 30.01.2015 um 14:41:02 Uhr
Goto Top
Die Systeme sind absolut gleich.
Sind alle auf einem Terminalserver.

Bei mir steht dort z.B. "NE15" dahinter.
Aber bei mir funktioniert es, obwohl ich diesen Zusatz NICHT in der Textdatei "druck.txt" aufgenommen habe face-wink

Ist doch seltsam...

LG
imebro
Mitglied: 114757
Lösung 114757 30.01.2015, aktualisiert am 03.02.2015 um 13:25:33 Uhr
Goto Top
Benutze die WMI-Variante von @colinardo die ist in dieser Hinsicht Systemübergreifend sowieso die bessere Variante. Bei ActivePrinter gibt es je nachdem wie der Drucker eingerichtet wurde eben ab und zu mal Probleme.
Gruß jodel32
Mitglied: 116301
116301 31.01.2015 aktualisiert um 15:39:47 Uhr
Goto Top
Hallo zusammen!

Beim Umstellen des Standarddruckers per WMI ändert sich leider nix an der ActivePrinter-Einstellung in Word...

Hier mal ein Code, mit dem es funktionieren sollte:
Private Declare Function GetProfileString Lib "kernel32" Alias "GetProfileStringA" ( _  
    ByVal lpAppName As String, _
    ByVal lpKeyName As String, _
    ByVal lpDefault As String, _
    ByVal lpReturnedString As String, _
    ByVal nSize As Long) As Long

Public Sub DeineSub()
    Call Printer("Müller_Blanko")  
    Call Printer("Müller_Brief")  
End Sub

Private Sub Printer(ByVal strName As String)
    Dim colPrinters As Object
    Dim strBuff As String, strPrinter As String, strDefaultPrinter As String
    
    strDefaultPrinter = ActivePrinter
            
    With GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")  
        Set colPrinters = .ExecQuery("Select * From Win32_Printer Where Name Like '%" & strName & "%'")  
        
        If colPrinters.Count Then
            strBuff = Space(1024)
            strPrinter = colPrinters.ItemIndex(0).Name
            
            GetProfileString "PrinterPorts", strPrinter, "", strBuff, Len(strBuff)  
    
            If InStr(strBuff, ",") Then  
               'strPrinter = strPrinter & " auf " & Split(strBuff, ",")(1)  'Deutsch  
                strPrinter = strPrinter & " on " & Split(strBuff, ",")(1)   'Englisch  
            End If
            
            On Error Resume Next
            ActivePrinter = strPrinter
            
            If Err.Number = 0 Then
                Application.PrintOut Filename:="", Range:=wdPrintAllDocument, Item:= _  
                wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _  
                Collate:=True, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
                PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
                ActivePrinter = strDefaultPrinter
            Else
                MsgBox "Drucker nicht gefunden: " & strName, vbExclamation, "Drucken . . ."  
            End If
            On Error GoTo 0
        Else
            MsgBox "Drucker nicht gefunden: " & strName, vbExclamation, "Drucken . . ."  
        End If
    End With
End Sub
Wobei die Vollständigkeit des Druckernamens unvollständig sein darf, da der Druckername anhand des angegebenen Teilnamens ermittelt wird z.B.
reicht "MX850" als Angabe für "Canon MX850 series Printer auf Ne02:"

Grüße Dieter
Mitglied: 37414
37414 03.02.2015 um 13:25:20 Uhr
Goto Top
Danke Dieter für Deinen Kommentar.

Ich werde es jetzt so lassen, wie es ist (also wie es VOR der Lösung mit der Textdatei "druck.txt" war).
Wird mir doch alles viel zu kompliziert und es funktioniert ja so bestens.

Zwar sind dann an jedem Arbeitsplatz jeweils individuelle Druckernamen im VBA-Script angegeben, aber da es sich nur um ein paar Mitarbeiter-/innen handelt, ist das vom Aufwand her ja nicht so dramatisch.

Nochmals danke für die Hilfe und LG,
imebro