Link to home
Start Free TrialLog in
Avatar of mattirons
mattironsFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Running Print Macros in a Terminal Server Session

Hi

I use print macros in Word and Excel to speed things up for my network users, but I'm having difficuity getting them to on our new Terminal Server. The user's local printers map okay, but once I've recorded the macro in their sessions it always tags the session id after the printer name. Which is fine (and the macros do work) until the user logs out and then logs back in. Once they do this the seesion id changes and the macro errors when they try to use it. Is there any piece of code out there that can fix this or another way I can code the macros to get around this problem. I'm not a massive VB user so this is all quite new stuff to me anyway.

Thanks in advance

Matt*
Avatar of lojk
lojk
Flag of United Kingdom of Great Britain and Northern Ireland image

pseudo code only, sorry. dont have a working VB6 machine to run this off...

dim PrinterToUse as printer
dim RequiredPrinterName as string
dim PrinterTestName
PrinterTestName="Epson" ' will set the RequiredPrinterName to the *last instance* of an epson printer
dim tP as printer
for each tp in printers
if instr(1,tp.name,PrinterTestname) then' A portion of the printers name was found in this printername
set printertouse=tP
next
end if
requiredPrinterName=printertouse.name

In some cases a user may have more than one printer(installed), you may need to pop up a dialog box to allow them to select it, the code above will also allow youto iterate that list into a a combobox for user selection.

I know exactly what you mean by your question, i have done quite a bit of TS/RDP development, if memeory serves it says 'PrinterName on SessionID'?, rather than use an instr function to check the name trim the end off by using
printername=left(Printername,instr(1,printername,'[space]on[space]session'))
and test/use that printername as required
oops...

for each tp in printers
if instr(1,tp.name,PrinterTestname) then' A portion of the printers name was found in this printername
set printertouse=tP
end if
next
Avatar of mattirons

ASKER

Hi

Thanks for your advise, I'll give the above a go over the next day or so and see if I can get it to work. I don;t generally do much vb programming (I just use the record macro function from within office, as apposed to wrtting the code), but I should be able to muddle through this hopefully.

Just so you know I have each user mapping 3 printers (one for each tray on the printer) which enables them to print to letterhead, continuation sheets and plain paper.......I take it'll I'll just have to duplicate the above for each instance of the printer being selected in the macro?

Thanks once again and I'll let you know how I get on!

Regards

Matt*
can you not display a drop down for tray and do a

printer.output tray = whateverthetrayworksoutforthecomboentry

rather than defining multiple printers?

Users are notoriously easy to confuse... ;-)
thanks dan
Hi Guys

Really sorry for the delay in getting back to you. I have been off work for nearly 5 weeks and so have let this one slip! (As nobody else has fixed the problem) I aim to have this resolved this week, so will feedback on the original solution ASAP.

Sorry once again and thanks again lojk!

Regards

Matt*
(*rolls eyes*)..... wish i could have five weeks off work...

;-)

just break a foot!
Only kidding, had a sneaky feeling it might have been an injury..

i had somebody knock me off my motorbike about his time last year and bust my elbow and was off for 6 weeks(you gotta make the most of these things ;-)), so i know how boring (for at least the first couple of weeks) that can be...

Glad you're back in one(ish) peice.
Yeah, me too. I wish I'd fallen off my motorbike again I only sprained my wrist last time I did! Broke my foot playing football......it hurt so much more than crashing did!!! :-)

I've had a play around with the above code you gave me before, but I can;t seem to get it to work. Any chance you could amend the following VB code (which is the working macro) so I can see where I should put the rename/trim printer name part?

    With ActiveDocument.PageSetup
        .LineNumbering.Active = False
        .Orientation = wdOrientPortrait
        .TopMargin = CentimetersToPoints(2.54)
        .BottomMargin = CentimetersToPoints(2.54)
        .LeftMargin = CentimetersToPoints(3.17)
        .RightMargin = CentimetersToPoints(3.17)
        .Gutter = CentimetersToPoints(0)
        .HeaderDistance = CentimetersToPoints(1.25)
        .FooterDistance = CentimetersToPoints(1.25)
        .PageWidth = CentimetersToPoints(21)
        .PageHeight = CentimetersToPoints(29.7)
        .FirstPageTray = 260
        .OtherPagesTray = 260
        .SectionStart = wdSectionNewPage
        .OddAndEvenPagesHeaderFooter = False
        .DifferentFirstPageHeaderFooter = False
        .VerticalAlignment = wdAlignVerticalTop
        .SuppressEndnotes = False
        .MirrorMargins = False
        .TwoPagesOnOne = False
        .GutterPos = wdGutterPosLeft
    End With
    ActivePrinter = "HP Tray 4 Plain (from MANAGER1) in session 3"
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub

This is just a third of the code I have the above twice before this part. First one prints page one to letterhead (specific tray on printer), the second part prints to continuation paper (specific tray on printer) and this part just prints one copy on plain paper (which again is a specific tray on the printer).

Reference your comment about not using lots of different printers, these users are (a pain in the arse!) used to using them as they have been working with 3 printers and macros for several years! I really do think it's just a case of getting the macro to call the printer without the session id attached, if that's possible.

Thanks in advance

Matt*
Ok, dont pile too much code into your subs...

add this function to the module/form

public function GetPrinterName (Clause1 as string , Clause2 as string,Clause3 as string ) as string
dim PrinterToUse as printer
dim requireprintername=""
dim tP as printer
for each tp in printers
if instr(1,tp.name,Clause1,1)>0 then' A portion of the printers name was found in this printername
if instr(1,tp.name,Clause2,1)>0 then' is it the correct tray?
'if instr(1,tp.name,Clause3,1)>0 then ' is it in the correct session 'currently remarked see below
'note the ,1 determines a case insensitive search
set printertouse=tP
requiredPrinterName=printertouse.name
'end if
end if
end if
next
return requiredprintername
exit function


then instead of
   ActivePrinter = "HP Tray 4 Plain (from MANAGER1) in session 3"
do
   ActivePrinter =GetPrinterName ("HP","Plain","")

notice that i have added the code to examine the session ID of the printername, this may or maynot be neccesary. if the code so far doesnt work we'll need to find a way to establish which session you are in and add that as the third clause (and unremark the two code lines)

i.e.

   ActivePrinter =GetPrinterName ("HP","Plain","session 3")

or

   ActivePrinter =GetPrinterName ("HP","Plain","MANAGER1")

Let us know how you get on..
Hi

I take it I need to add the above to the beginning of the module? If so it errors straight away with compile Error - Exepcted End Sub.....???
I also noticed that the dim requireprintername="" and return requiredprintername turn to red when I put them in the module!

BTW - As mentioned before I only ever make macros via the record function in Word and Excel (not via code), so I guess it's Microsoft adding all the extra lines in. Am I right in thinkng that the only thing I need to really specify on the With ActiveDocument.PageSetup part is the trays?

Regards

Matt*

yeah sorry had just written all this code 'by hand' and yes there was a spelling mistake or two..

should look like this... (truncated the subs for simplicity)


------------------------------
       .GutterPos = wdGutterPosLeft
    End With
    ActivePrinter = GetPrinterName ("HP","Continuation","")''or whatever
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub

----------------------------
   ActivePrinter = GetPrinterName ("HP","Letterhead","")''or whatever
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub
------------------------------
       .GutterPos = wdGutterPosLeft
    End With
    ActivePrinter = GetPrinterName ("HP","Plain","")''or whatever
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub

public function GetPrinterName (Clause1 as string , Clause2 as string,Clause3 as string ) as string
dim PrinterToUse as printer
dim requiredprintername as string
dim tP as printer
for each tp in printers
if instr(1,tp.name,Clause1,1)>0 then' A portion of the printers name was found in this printername
if instr(1,tp.name,Clause2,1)>0 then' is it the correct tray?
'if instr(1,tp.name,Clause3,1)>0 then ' is it in the correct session 'currently remarked see below
'note the ,1 determines a case insensitive search
set printertouse=tP
requiredPrinterName=printertouse.name
'end if
end if
end if
next
GetPrinterName =requiredprintername
exit function

you obviously only need to add the function once (at the bottom of all the other subs) but change the 'Activeprinter=' line accordingly (as i have shown above)

VBA is rather fussy with default values so leave all the generated code 'as is', you may prefer to remove them line by line once you are sorted...

Please reread my previous comment however because it does offer some major hints on making this all work a bit better, even if you're not 'a coder' :-)
I have got the first part (all the subs) running fine, well it doesn't error anymore, but it now stops at the 'PrinterToUse as printer' line. It errors with Compile Error: User-defined Type Not Defined.

Also when I pasted the public function into the module it put it into it's own one below the three subs' section. Is this right?
yep thats correct, its a 'function' that other code can use (its a function because it 'returns' a value)..


Finally copied the funciton into a word instance on a TermSrvr.. turns out there is no 'printers' collection or 'printer' type (as there is in VB6).. oops, sorry!

the function should read...



Public Function GetPrinterName(Clause1 As String, Clause2 As String, Clause3 As String) As String
Dim PrinterToUse
Dim requiredprintername As String
Dim tP As String
tP = fEnumeratePrinters4

Dim tps() As String
tps = Split(tP, Chr(13))
Dim tc As Integer
For tc = 0 To UBound(tps) - 1
 
If InStr(1, tps(tc), Clause1, 1) > 0 Then ' A portion of the printers name was found in this printername
If InStr(1, tps(tc), Clause2, 1) > 0 Then ' is it the correct tray?
'if instr(1,tps(tc),Clause3,1)>0 then ' is it in the correct session 'currently remarked see below
'note the ,1 determines a case insensitive search
requiredprintername = tps(tc)
'end if
End If
End If
Next
GetPrinterName = requiredprintername
End Function

and you also need to add a new module to the project that contains exactly this text... (assuming NT4/win2k/xp)

Option Explicit

      Const PRINTER_ENUM_CONNECTIONS = &H4
      Const PRINTER_ENUM_LOCAL = &H2

      Type PRINTER_INFO_1
         flags As Long
         pDescription As String
         PName As String
         PComment As String
      End Type

      Type PRINTER_INFO_4
         pPrinterName As String
         pServerName As String
         Attributes As Long
      End Type

      Declare Function EnumPrinters Lib "winspool.drv" Alias _
         "EnumPrintersA" (ByVal flags As Long, ByVal name As String, _
         ByVal Level As Long, pPrinterEnum As Long, ByVal cdBuf As Long, _
         pcbNeeded As Long, pcReturned As Long) As Long
      Declare Function PtrToStr Lib "Kernel32" Alias "lstrcpyA" _
         (ByVal RetVal As String, ByVal Ptr As Long) As Long
      Declare Function StrLen Lib "Kernel32" Alias "lstrlenA" _
         (ByVal Ptr As Long) As Long
                   
                   
                   

 Sub EnumeratePrinters1()
      Dim Success As Boolean, cbRequired As Long, cbBuffer As Long
      Dim Buffer() As Long, nEntries As Long
      Dim I As Long, PFlags As Long, PDesc As String, PName As String
      Dim PComment As String, Temp As Long
         cbBuffer = 3072
         ReDim Buffer((cbBuffer \ 4) - 1) As Long
         Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                               PRINTER_ENUM_LOCAL, _
                               vbNullString, _
                               1, _
                               Buffer(0), _
                               cbBuffer, _
                               cbRequired, _
                               nEntries)
         If Success Then
            If cbRequired > cbBuffer Then
               cbBuffer = cbRequired
               Debug.Print "Buffer too small.  Trying again with " & _
                        cbBuffer & " bytes."
               ReDim Buffer(cbBuffer \ 4) As Long
               Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                   PRINTER_ENUM_LOCAL, _
                                   vbNullString, _
                                   1, _
                                   Buffer(0), _
                                   cbBuffer, _
                                   cbRequired, _
                                   nEntries)
               If Not Success Then
                  Debug.Print "Error enumerating printers."
                  Exit Sub
               End If
            End If
         Debug.Print "There are " & nEntries & _
                      " local and connected printers."
         For I = 0 To nEntries - 1
            PFlags = Buffer(4 * I)
            PDesc = Space$(StrLen(Buffer(I * 4 + 1)))
            Temp = PtrToStr(PDesc, Buffer(I * 4 + 1))
            PName = Space$(StrLen(Buffer(I * 4 + 2)))
            Temp = PtrToStr(PName, Buffer(I * 4 + 2))
            PComment = Space$(StrLen(Buffer(I * 4 + 2)))
            Temp = PtrToStr(PComment, Buffer(I * 4 + 2))
            Debug.Print PFlags, PDesc, PName, PComment
         Next I
         Else
            Debug.Print "Error enumerating printers."
         End If
      End Sub

      Sub EnumeratePrinters4()
      Dim Success As Boolean, cbRequired As Long, cbBuffer As Long
      Dim Buffer() As Long, nEntries As Long
      Dim I As Long, PName As String, SName As String
      Dim Attrib As Long, Temp As Long
         cbBuffer = 3072
         ReDim Buffer((cbBuffer \ 4) - 1) As Long
         Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                               PRINTER_ENUM_LOCAL, _
                               vbNullString, _
                               4, _
                               Buffer(0), _
                               cbBuffer, _
                               cbRequired, _
                               nEntries)
         If Success Then
            If cbRequired > cbBuffer Then
               cbBuffer = cbRequired
               Debug.Print "Buffer too small.  Trying again with " & _
                        cbBuffer & " bytes."
               ReDim Buffer(cbBuffer \ 4) As Long
               Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                   PRINTER_ENUM_LOCAL, _
                                   vbNullString, _
                                   4, _
                                   Buffer(0), _
                                   cbBuffer, _
                                   cbRequired, _
                                   nEntries)
               If Not Success Then
                  Debug.Print "Error enumerating printers."
                  Exit Sub
               End If
            End If
            Debug.Print "There are " & nEntries & _
                      " local and connected printers."
            For I = 0 To nEntries - 1
            PName = Space$(StrLen(Buffer(I * 3)))
            Temp = PtrToStr(PName, Buffer(I * 3))
            SName = Space$(StrLen(Buffer(I * 3 + 1)))
            Temp = PtrToStr(SName, Buffer(I * 3 + 1))
            Attrib = Buffer(I * 3 + 2)
            Debug.Print "Printer: " & PName, "Server: " & SName, _
                        "Attributes: " & Hex$(Attrib)
            Next I
         Else
            Debug.Print "Error enumerating printers."
         End If
      End Sub
Function fEnumeratePrinters4() As String
      Dim Success As Boolean, cbRequired As Long, cbBuffer As Long
      Dim Buffer() As Long, nEntries As Long
      Dim I As Long, PName As String, SName As String
      Dim Attrib As Long, Temp As Long
     
      Dim tRet As String
     
         cbBuffer = 3072
         ReDim Buffer((cbBuffer \ 4) - 1) As Long
         Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                               PRINTER_ENUM_LOCAL, _
                               vbNullString, _
                               4, _
                               Buffer(0), _
                               cbBuffer, _
                               cbRequired, _
                               nEntries)
         If Success Then
            If cbRequired > cbBuffer Then
               cbBuffer = cbRequired
               Debug.Print "Buffer too small.  Trying again with " & _
                        cbBuffer & " bytes."
               ReDim Buffer(cbBuffer \ 4) As Long
               Success = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                                   PRINTER_ENUM_LOCAL, _
                                   vbNullString, _
                                   4, _
                                   Buffer(0), _
                                   cbBuffer, _
                                   cbRequired, _
                                   nEntries)
               If Not Success Then
                  Debug.Print "Error enumerating printers."
                  Exit Function
               End If
            End If
            Debug.Print "There are " & nEntries & _
                      " local and connected printers."
            For I = 0 To nEntries - 1
            PName = Space$(StrLen(Buffer(I * 3)))
            Temp = PtrToStr(PName, Buffer(I * 3))
            SName = Space$(StrLen(Buffer(I * 3 + 1)))
            Temp = PtrToStr(SName, Buffer(I * 3 + 1))
            Attrib = Buffer(I * 3 + 2)
            Debug.Print "Printer: " & PName, "Server: " & SName, _
                        "Attributes: " & Hex$(Attrib)
                        tRet = tRet + PName & Chr(13)
            Next I
         Else
            Debug.Print "Error enumerating printers."
         End If
         fEnumeratePrinters4 = tRet
      End Function



so try that, and let me know if that works (ceratinly returns the correct printers on my machine from a word session).. like i said before we may need to resolve the sessionid too, but i have found out *how* but not written a sub for it yet...
Wow! I won;t even ask what all that does!!!! Thanks.....

Ok, I've just added the amended Public function.

I have copy and pasted the whole of the other code too. Once I'd done this it obviously put each sub function into it's own module.  But the Option Explicit will not go into it's own, it keeps getting included after the Public Function (which then errors because you can only have comments after an End Function command!

Any ideas???? Do I just move the End command to after the Option Explicit or not?

Thanks

Matt*
ok the large block of code should go into a module on its own *Exactly* as it is there should be no reason for it to split anything up.

to surmise.

either

you should have one module (look in the project window on the left in the VB code editor, right click and 'add new module' if neccesary) that contains your three subs and my 'GetPrinterName ' function *AND* you should have another module contaiing (only) the large block of code with several subs and functions from above (i.e. from 'Option Explicit' to the last 'end function').

or (probably easier)

you should have one module containing the large block of code with several subs and functions from above (i.e. from 'Option Explicit' to the last 'end function') *THEN* my 'GetPrinterName ' function *THEN* your three subs.
Ok, this is lokking really good. I did the above late last night and the code ran fine, but working remotely I couldn't see what actually printed! I have this morning though and it's worked fine! Just tried it again ans it still works in a different session!!!

Thank you very much for this. I'm going to go live with two users at lunchtime so that I can get them to test it before I roll it out to all users. If it's ok with you I'd like to leave this open untill Tuesday (the day I will deploy the solution to all users), just in case there are any hiccups.

Let me know if this is ok and thanks once again your a star!

A Very Happy MAtt*
Thats fine Matt.. Like i said im still open to the possiblity that we may need to adjust the code to compensate for session ids (especially once more than one of them is using it) but from what you say you are printing *internally* and not to their local printers? It shoudnt be a factor with a bit of luck..

I'm here to help, for fun(?!) and cos it makes me feel "warm 'n' fluffy" knowing I've saved you from pulling a few clumps of hair (and perhaps taught us both a couple of things along the way). You might be surprised however, if i told you how little VBA work i actually do!

Yeah, "roll 'er out" and let us know.. I'll monitor the thread...

A, happy that you're happy, *INSERT REAL NAME HERE* ;-)

**Latest Update**

I've just got the macros working on two different machines (with just a little fine tuning on the printer set up) and it's working great in Word! I tried to get the same macro to work in Excel and it errors on the page setup part (which is understandable as Excel doesn't have the same quirky page setup options as Word does). So I changed the macro to:

Sub QuotePrint()
'
' QuotePrint Macro
' Macro recorded 22/08/2006 by FOSTERS

  ActivePrinter = GetPrinterName("HP", "Letterhead", "")
    Application.PrintOut Filename:="", Range:=wdPrintRangeOfPages, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="1", PageType:=wdPrintAllPages, _
         Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0 _
        , PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
  ActivePrinter = GetPrinterName("HP", "Continuation", "")
    Application.PrintOut Filename:="", Range:=wdPrintRangeOfPages, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="2", PageType:=wdPrintAllPages, _
         Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0 _
        , PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
  ActivePrinter = GetPrinterName("HP", "Plain", "")
    Application.PrintOut Filename:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=2, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
     End Sub

Basically stripping out the page setup bits and now it errors on the first ActivePrinter line. The error message reads:

Run-Time Error '1004'

Method 'ActivePrinter' of object '_Global' failed

Just to rule this out I have added the GetPrinterName sub and a new module with the Option Explicit code in.
I guess this is erroring because it's been written specifically for Word and so some of the code will need to be changed inorder for in to work in Excel.

Is this right or am I barking up the wrong tree?????? And can you help?

Thanks once again

Matt*
think the obvious answer is to 'rinse and repeat'

i.e.

as  above....

you should have one module containing the large block of code with several subs and functions from above (i.e. from 'Option Explicit' to the last 'end function') *THEN* my 'GetPrinterName ' function *THEN* rerecord the three macros in excel as you had in word and those to the end.

which seems to be what youve done so far in your last comment..

have just checked on my excel here, you are correct, there is no global object for the activeprinter - you pass the active printer name throught the printout command


eg..

dim tActivePrinterName as string
tActivePrinterName = GetPrinterName("HP", "Plain", "")
Application.PrintOut Filename:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=2, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0 , ActivePrinter:=tActivePrinterName
     End Sub


That made it work?
Nearly!

The module now reads:

Sub QuotePrint()
'
' QuotePrint Macro
' Macro recorded 22/08/2006 by FOSTERS

  Dim tActivePrinterName As String
tActivePrinterName = GetPrinterName("HP", "Letterhead", "")
Application.PrintOut Filename:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="1", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0, ActivePrinter:=tActivePrinterName
tActivePrinterName = GetPrinterName("HP", "Continuation", "")
Application.PrintOut Filename:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="2", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0, ActivePrinter:=tActivePrinterName
tActivePrinterName = GetPrinterName("HP", "Plain", "")
Application.PrintOut Filename:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=2, Pages:="", PageType:=wdPrintAllPages, _
        Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0, _
         PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0, ActivePrinter:=tActivePrinterName
     End Sub

But it errors when it gets to each of the Application.PrintOut Filename part with:

Run-Time Error '483'

Object doesn't support this property or method.
Hmm i dont know, the macro i recorded says just this..

    ActiveWindow.SelectedSheets.PrintOut Copies:=1, ActivePrinter:= tActivePrinterName, Collate:=True

i would suggest removing some of the clutter from your print commands, property pair by property pair until it starts to work.

the example in the help file says...

expression.PrintOut(From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName)

so i guess (for the last macro block) you could try this instead..

tActivePrinterName = GetPrinterName("HP", "Plain", "")
Application.PrintOut (1,1,2,false,tActivePrinter,false,false,"")
Silly me, I should have spotted that one! I've changed it to:

Sub QuotePrint()
'
' QuotePrint Macro
' Macro recorded 22/08/2006 by FOSTERS

  Dim tActivePrinterName As String
tActivePrinterName = GetPrinterName("HP", "Letterhead", "")
ActiveWindow.SelectedSheets.PrintOut From:=1, To:=1, Copies:=1, _
ActivePrinter:=tActivePrinterName
tActivePrinterName = GetPrinterName("HP", "Continuation", "")
ActiveWindow.SelectedSheets.PrintOut From:=2, To:=2, Copies:=1, _
ActivePrinter:=tActivePrinterName
tActivePrinterName = GetPrinterName("HP", "Plain", "")
ActiveWindow.SelectedSheets.PrintOut Copies:=2, _
ActivePrinter:=tActivePrinterName
     End Sub

And it works!!!!!!!!!! Hooray! Any ideas on why it would print really, really, really slow ? Just been told by one of the testers that Word prnts really slow too!
you could try (in word) (I cannot find any equivalent setting in Excel)

Tools | Options || Print | Background Printing

to off. That usually fixes it but maybe in a TS environment with many attached users and printers it might take a second or two to index the printer from the list. Depends on how slow, 'slow' is i suppose.. perhaps its just a server side load issue? Are you sure that 'spooling' is set up correctly for those printers?

I know that collate = true will also decrease speed because it has to render the pages back to front and is therefore inherently slow..


First thing I checked was the printer spooling settings and they seem to be optimized for performance....I'll have a play around tonight and let you know.

Thanks once again for all your help.

Matt*

P.S. I'll try removing the Collate part from the Word macro and see if it makes a difference!
Me again! And not great news I'm afraid!

The machine I was testing everything on works a treat, but I now have the following problem for the other users. If I try to use the network printer that is installed on the client PC, it doesn;t appear in the TS Session and so I can't print anything! However on the test machine they do map across and the macro works fine! (this machine had just been formatted and reinstalled with a fresh copy of XP and SP2, all the other machines are also XP And SP2, so haven;t got a clue why one does and the other doesn't!) Is there anyway that you know of that enables you to map network printers? They are just HP Laserjets printing through a local TCP/IP Port.
Failing I'll have to install the printers from a share on the network server, browse netowkr, right click printer and connect. When I do this the code fails to find the printer! However when you actually step through the code manually it can see all 3 printers , but once it's run the GetPrinterNAme module is errors at the

ActivePrinter = GetPrinterName ("HP","Letterhead","") line with Runtime Error 5216 - There was a printer error!

The difference in printer name is as follows:

When the locally installed printer connects the printer is called HP Tray 2 Letterhead and the macro finds this printer and prints to it.
When the shared server printer connects the printer is called HP Tray 2 Letterhead on sbs-rams (from CONVEY34) in session 5 and the macro then fails to find the printer. (Even though it see's them all when you step through manually!)

I have tried to add an extra Clause4 string it the ActivePrinter line and the GetPrinterName module for the sbs-rams part but it stills fails....any ideas?

I feel we're so close, but still just a little way off!!

Regards

Matt*
OK, firstly i dont think network printers are mapped under ts2000, only locally attached ones ( i dont even think USB count as locally mapped) ..

see here for suggestions

https://www.experts-exchange.com/questions/21952309/Windows-XP-clients-printing-to-TCP-IP-printers-via-terminal-Service-Session.html

As for differences, check that you are using the latest (i.e. remote desktop connection) client and ensure on the resources tab that 'map printers' is ticked.

adding printers on demand, this is the same as the right click method you describe
add a new batch file with this line
cmd /c net use \\servername\ServerPrinterSharename

an extra clause 4 is not nececsary, thats what the clause3 is for (i already knew we might need to add one more find category), its currently unuused..


We need to break this down into its smallest units, lets deal with these issues first before attempting the big one...

I need you to define the setup a bit better, my best guess goes a bit like this..

One TS Server, 1 Printer (The HP Laser)
Several users, multiple printers mapped to the server HP with differing default print properties (trays)

on TS Session user prints to the server printer (not expecting an output at their desk but on a central printer)?

oh, one quick question, are al lthe users working within the local netwokr or is this intended to allow them to work at home etc..?

If it is only local network, or they connect via a VPN first before TSing to the server then you may not need to map the printers in this way.. You may be able to add them directyl to the users profile.
Ok, just to clarify the set up.

We have a central office (that runs the accounts and SQL Doc management system). This is run by an SBS 2003 box and also has a 2003 TS box.
We have 3 remote offices all running their own network and SBS box and each having an HP Laserjet 4200dtn printer and a Canon colour copier/printer/fax etc. All users at each site share one of the printers. They are all installed locally on each PC 3 times in order to simplify their printing. HP Tray 2 Letterhead, HP Tray 3 Continuation, etc, etc. I have noticed that some of them have 3 seperatet TCP/IP Ports and others have only one port on them.
The offices connect to eachother via a permanent VPN solution i.e. always up tunnel. This enables users to browse file servers at each location using the local IP Address of the machine. (I guess if they really wanted to they could even print via IP across the VPN too.

I currently have one machine that will map the network printer in it's TS Session (not sure how it manages this), but none of the other machine will!

I therefore either need to get them all to map their network printer connection or install them all differently and get the code to recognise the printer when it's name is: HP Tray 2 Letterhead on sbs-rams (from CONVEY34) in session 5 etc.

Does that make things any clearer??????

 
ok  thanks for that will read through that in mre detail later.

I'm not near a pc today (tapping this on my phone) though so won't be able to follow this up till later sorry. Willl give me some time to think about it anyway.
ok first things first, lets see your options....

ok change the function to this

Public Function GetPrinterName(Clause1 As String, Clause2 As String, Clause3 As String) As String
Dim PrinterToUse
Dim requiredprintername As String
Dim tP As String
tP = fEnumeratePrinters4
debug.print tp ''''i.e. just add this line
Dim tps() As String
tps = Split(tP, Chr(13))
Dim tc As Integer
For tc = 0 To UBound(tps) - 1
 
If InStr(1, tps(tc), Clause1, 1) > 0 Then ' A portion of the printers name was found in this printername
If InStr(1, tps(tc), Clause2, 1) > 0 Then ' is it the correct tray?
'if instr(1,tps(tc),Clause3,1)>0 then ' is it in the correct session 'currently remarked see below
'note the ,1 determines a case insensitive search
requiredprintername = tps(tc)
'end if
End If
End If
Next
GetPrinterName = requiredprintername
End Function

allow the function to run on several machine (i.e at least one that does work, at least one that doesnt) and then look in the output or console window of the visual basic editor it should print the identified printers for that session, please copy and paste that (with details of each machines name that it was run on at the time) into here...

Please post as much detail as possible, i am currently working on a quick function to determine the current session number and machine name but i will need this info to finish the previous function.

Im sure we can do it, i fear at the very worst we might need to add some net use commands to map your ip printers to an lpt port...

cheers


Hi

I've just changed the function as per the above, but now when I run the macro it errors on the first ActivePrinter = GetPrinterName ("HP","Letterhead","") line (on the GetPrinterName part) with:

Compile Error
Wrong number of arguements or invalid property assignment!
ok it sounds like you have changed the function since the one i have posted, note i only wanted you to add the 'debug.print tp' line..

I seem to remember you saying something about adding another clause parameter earlier..

Please post a copy of your existing function and preferably one of the macro subs that calls it...

My mistake, you were right...I removed the extra claus bits so I have this calling it:

ActivePrinter = GetPrinterName("HP", "Letterhead", "")
    Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="1", PageType:=wdPrintAllPages, _
         Collate:=False, Background:=True, PrintToFile:=False, PrintZoomColumn:=0 _
        , PrintZoomRow:=0, PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0

And the module is:

Public Function GetPrinterName(Clause1 As String, Clause2 As String, Clause3 As String) As String
Dim PrinterToUse
Dim requiredprintername As String
Dim tP As String
tP = fEnumeratePrinters4
Debug.Print tP
Dim tps() As String
tps = Split(tP, Chr(13))
Dim tc As Integer
For tc = 0 To UBound(tps) - 1
 
If InStr(1, tps(tc), Clause1, 1) > 0 Then ' A portion of the printers name was found in this printername
If InStr(1, tps(tc), Clause2, 1) > 0 Then ' is it the correct tray?
'if instr(1,tps(tc),Clause3,1)>0 then ' is it in the correct session 'currently remarked see below
'note the ,1 determines a case insensitive search
requiredprintername = tps(tc)

Did I add the debug part in the right place, because now when I run it it just gives me the Runtime Error 5216 - There is a printer error message.
It doesn't print/list anything to screen!
'end if
End If
End If
Next
GetPrinterName = requiredprintername
End Function
Hmmm.. sounds like you are getting a bit confused with this... Please do all testing on the original machine you were testing with for now.

just remove the 'debug.print tP' line for now...

then highlight or select some text within the (every) line that begins...

"Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _"

(i.e. the line *after* the 'ActivePrinter = GetPrinterName("HP", "Letterhead", "")'

and press 'F9' or Debug Menu | Toggle Breakpoint

the line should go red indicating that execution will stop at that line..

run the macro, it should stop at your breakpoint.
now from the View Menu choose 'Immediate Window' and scroll to the bottom of the list to view the last list of printers that it found. Its this listt that i need to see...

on mine it looks a bit like this..

There are 3 local and connected printers.
Printer: HP Continuation    Server:       Attributes: 240
Printer: HP Plain           Server:       Attributes: 240
Printer: Samsung ML-4500 Series           Server:       Attributes: 2048

which shows the two 'fake' printers ive added to test with and my local (real) samsung printer.


Ok sorry......

Right this is what the machine that works (the one with locally installed network printers that map themselfs in the TS session) says:

There are 3 local and connected printers.
Printer: HP Tray 4 Plain (from MANAGER1) in session 12  Server:       Attributes: 8240
Printer: HP Tray 3 Continuation (from MANAGER1) in session 12         Server:       Attributes: 8240
Printer: HP Tray 2 Letterhead (from MANAGER1) in session 12           Server:       Attributes: 8240

And this is what the machine that doesn;t work (the one which doesn't map the printers, but does have the printer which is shared from the server appearing) says:

There are 4 local and connected printers.
Printer: HP Tray 2 Letterhead on sbs-rams (from CONVEY30) in session 14             Server:       Attributes: 8240
Printer: HP Tray 3 Continuation on sbs-rams (from CONVEY30) in session 14           Server:       Attributes: 8240
Printer: HP Tray 4 Plain on sbs-rams (from CONVEY30) in session 14    Server:       Attributes: 8240
Printer: HPTFB1 on sbs-rams (from CONVEY30) in session 14             Server:       Attributes: 8240
ASKER CERTIFIED SOLUTION
Avatar of lojk
lojk
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial