+ Reply to Thread
Results 1 to 13 of 13

Thread: Print Duplex

  1. #1
    Registered User
    Join Date
    05-11-2010
    Location
    A far away land
    MS-Off Ver
    Excel 2003
    Posts
    38

    Question Print Duplex

    I am running two macros to print selections of a sheet. They are both included below. Can I add a setting somewhere in the macro to make them print duplex.

    1st

    With ActiveSheet.PageSetup
            .PrintArea = "bq19:cl99"
            .PrintTitleRows = ""
            .PrintTitleColumns = ""
            .LeftHeader = ""
            .CenterHeader = ""
            .RightHeader = ""
            .LeftFooter = ""
            .CenterFooter = ""
            .RightFooter = ""
            .LeftMargin = Application.InchesToPoints(0)
            .RightMargin = Application.InchesToPoints(0)
            .TopMargin = Application.InchesToPoints(0)
            .BottomMargin = Application.InchesToPoints(0)
            .HeaderMargin = Application.InchesToPoints(0)
            .FooterMargin = Application.InchesToPoints(0)
            .PrintHeadings = False
            .PrintGridlines = False
            .PrintComments = xlPrintNoComments
            .CenterHorizontally = True
            .CenterVertically = True
            .Orientation = xlLandscape
            .Draft = False
            .PaperSize = xlPaperLetter
            .FirstPageNumber = xlAutomatic
            .Order = xlOverThenDown
            .BlackAndWhite = False
            .Zoom = False
            .FitToPagesTall = 1
            .FitToPagesWide = 1
            
        End With
        
    
        ActiveSheet.PrintOut Copies:=1, Collate:=True
        Range("A1").Select
    
        
       Range("a1").Select
    End Sub
    2nd

      Range("W1:AH38").Select
        Selection.PrintOut Copies:=1, Collate:=True
    End Sub
    I am running both macros at the same time in a seperate macro and calling on both macros I just didnt know if it was possible or where it would go.

    Thanks

  2. #2
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & read 2007
    Posts
    15,979

    Re: Print Duplex

    Hello Redeoclown,

    Unfortunately VBA did not add a Printer Object as Visual Basic did. If Microsoft had then this would wouldn't be so difficult. Actually, I have done the difficult part for you. Copy all of this code into a separate VBA module. This is what is needed to set a printer to duplex or back to simplex mode.
    'Written: June 17, 2010
    'Author:  Leith Ross
    'Summary: Sets a printer to Duplex mode or back to Simplex. There are 2 duplex settings:
    '         Book style and Legal (Flip) style. See comment box below for the values.
    
    
       Public Type PRINTER_DEFAULTS
           pDatatype As Long
           pDevmode As Long
           DesiredAccess As Long
       End Type
    
       Type PRINTER_INFO_2
           pServerName As Long
           pPrinterName As Long
           pShareName As Long
           pPortName As Long
           pDriverName As Long
           pComment As Long
           pLocation As Long
           pDevmode As Long             ' Pointer to DEVMODE
           pSepFile As Long
           pPrintProcessor As Long
           pDatatype As Long
           pParameters As Long
           pSecurityDescriptor As Long  ' Pointer to SECURITY_DESCRIPTOR
           Attributes As Long
           Priority As Long
           DefaultPriority As Long
           StartTime As Long
           UntilTime As Long
           Status As Long
           cJobs As Long
           AveragePPM As Long
       End Type
    
       Type DEVMODE
           dmDeviceName As String * 32
           dmSpecVersion As Integer
           dmDriverVersion As Integer
           dmSize As Integer
           dmDriverExtra As Integer
           dmFields As Long
           dmOrientation As Integer
           dmPaperSize As Integer
           dmPaperLength As Integer
           dmPaperWidth As Integer
           dmScale As Integer
           dmCopies As Integer
           dmDefaultSource As Integer
           dmPrintQuality As Integer
           dmColor As Integer
           dmDuplex As Integer
           dmYResolution As Integer
           dmTTOption As Integer
           dmCollate As Integer
           dmFormName As String * 32
           dmUnusedPadding As Integer
           dmBitsPerPel As Integer
           dmPelsWidth As Long
           dmPelsHeight As Long
           dmDisplayFlags As Long
           dmDisplayFrequency As Long
           dmICMMethod As Long
           dmICMIntent As Long
           dmMediaType As Long
           dmDitherType As Long
           dmReserved1 As Long
           dmReserved2 As Long
       End Type
    
       Const DM_DUPLEX = &H1000&
       Const DM_IN_BUFFER = 8
    
       Const DM_OUT_BUFFER = 2
       Const PRINTER_ACCESS_ADMINISTER = &H4
       Const PRINTER_ACCESS_USE = &H8
       Const STANDARD_RIGHTS_REQUIRED = &HF0000
       Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
                                   PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
    
       Private Declare Function ClosePrinter _
         Lib "winspool.drv" _
           (ByVal hPrinter As Long) _
         As Long
        
       Private Declare Function DocumentProperties _
         Lib "winspool.drv" _
           Alias "DocumentPropertiesA" _
             (ByVal hWnd As Long, _
              ByVal hPrinter As Long, _
              ByVal pDeviceName As String, _
              ByVal pDevModeOutput As Long, _
              ByVal pDevModeInput As Long, _
              ByVal fMode As Long) _
         As Long
         
       Private Declare Function GetPrinter _
         Lib "winspool.drv" _
           Alias "GetPrinterA" _
             (ByVal hPrinter As Long, _
              ByVal Level As Long, _
              ByRef pPrinter As Byte, _
              ByVal cbBuf As Long, _
              ByRef pcbNeeded As Long) _
         As Long
         
       Private Declare Function OpenPrinter _
         Lib "winspool.drv" _
           Alias "OpenPrinterA" _
             (ByVal pPrinterName As String, _
              ByRef phPrinter As Long, _
              ByRef pDefault As PRINTER_DEFAULTS) _
         As Long
         
       Private Declare Function SetPrinter _
         Lib "winspool.drv" _
         Alias "SetPrinterA" _
           (ByVal hPrinter As Long, _
             ByVal Level As Long, _
             ByRef pPrinter As Byte, _
             ByVal Command As Long) _
         As Long
    
       Private Declare Sub CopyMemory _
         Lib "kernel32" _
           Alias "RtlMoveMemory" _
             (ByRef pDest As Any, _
              ByRef pSource As Any, _
              ByVal cbLength As Long)
     
       Private Declare Function StrLen _
         Lib "kernel32" _
           Alias "lstrlenA" _
             (ByVal lpString As Long) As Long
     
       ' ==================================================================
       ' SetPrinterToDuplex.
       '
       '  Set the Duplex flag for the specified default properties
       '  of the printer driver.
       '
       '  Returns: True on success and False on error. An error will also
       '  display a message box. These messages are displayed for information
       '  only.
       '
       '  Parameters:
       '    PrinterName - The name of the printer to be used as an ANSI string.
       '
       '    DuplexSetting - One of the following standard settings:
       '       1 = None
       '       2 = Duplex on long edge (book)
       '       3 = Duplex on short edge (legal)
       '
       ' ==================================================================
       Public Function SetPrinterToDuplex(ByVal PrinterName As String, _
                                          ByVal DuplexSetting As Long) As Boolean
    
          Dim hPrinter As Long
          Dim PD As PRINTER_DEFAULTS
          Dim PINFO As PRINTER_INFO_2
          Dim DM As DEVMODE
       
          Dim DevModeData() As Byte
          Dim PInfoMemory() As Byte
          Dim nBytesNeeded As Long
          Dim nRet As Long, nJunk As Long
       
          On Error GoTo cleanup
       
          If (DuplexSetting < 1) Or (DuplexSetting > 3) Then
             MsgBox "Error: dwDuplexSetting is incorrect."
             Exit Function
          End If
          
          PD.DesiredAccess = PRINTER_ALL_ACCESS
          nRet = OpenPrinter(PrinterName, hPrinter, PD)
          If (nRet = 0) Or (hPrinter = 0) Then
             If Err.LastDllError = 5 Then
                MsgBox "Access denied."
             Else
                MsgBox "Cannot open the printer specified " & _
                  "(make sure the printer name is correct)."
             End If
             Exit Function
          End If
       
          nRet = DocumentProperties(0&, hPrinter, PrinterName, 0&, 0&, 0&)
          If (nRet < 0) Then
             MsgBox "Cannot get the size of the DEVMODE structure."
             GoTo cleanup
          End If
       
          ReDim DevModeData(nRet + 100) As Byte
          nRet = DocumentProperties(0&, hPrinter, PrinterName, _
                      VarPtr(DevModeData(0)), 0&, DM_OUT_BUFFER)
          If (nRet < 0) Then
             MsgBox "Cannot get the DEVMODE structure."
             GoTo cleanup
          End If
       
          Call CopyMemory(DM, DevModeData(0), Len(DM))
       
          If Not CBool(DM.dmFields And DM_DUPLEX) Then
            MsgBox "You cannot modify the duplex flag for this printer " & _
                   "because it does not support duplex or the driver " & _
                   "does not support setting it from the Windows API."
            GoTo cleanup
          End If
       
          DM.dmDuplex = DuplexSetting
          Call CopyMemory(DevModeData(0), DM, Len(DM))
       
          nRet = DocumentProperties(0&, hPrinter, PrinterName, _
            VarPtr(DevModeData(0)), VarPtr(DevModeData(0)), _
            DM_IN_BUFFER Or DM_OUT_BUFFER)
    
          If (nRet < 0) Then
            MsgBox "Unable to set duplex setting to this printer."
            GoTo cleanup
          End If
       
          Call GetPrinter(hPrinter, 2&, 0&, 0&, nBytesNeeded)
          If (nBytesNeeded = 0) Then GoTo cleanup
       
          ReDim PInfoMemory(nBytesNeeded + 100) As Byte
    
          nRet = GetPrinter(hPrinter, 2&, PInfoMemory(0), nBytesNeeded, nJunk)
          If (nRet = 0) Then
             MsgBox "Unable to get shared printer settings."
             GoTo cleanup
          End If
       
          Call CopyMemory(PINFO, PInfoMemory(0), Len(PINFO))
            PINFO.pDevmode = VarPtr(DevModeData(0))
            PINFO.pSecurityDescriptor = 0
          Call CopyMemory(PInfoMemory(0), PINFO, Len(PINFO))
       
          nRet = SetPrinter(hPrinter, 2&, PInfoMemory(0), 0&)
          If (nRet = 0) Then
             MsgBox "Unable to set shared printer settings."
          End If
       
          SetPrinterToDuplex = CBool(nRet)
    
    cleanup:
          If (hPrinter <> 0) Then Call ClosePrinter(hPrinter)
    
    End Function

    Example for Setting the ActivePrinter to Duplex (Book style)
    Sub DuplexTest()
    
      Dim PrinterName As String
        
        PrinterName = Application.ActivePrinter
        SetPrinterToDuplex Left(PrinterName, InStr(1, PrinterName, " on") - 1), 2
        
    End Sub
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  3. #3
    Registered User
    Join Date
    01-25-2011
    Location
    Virginia
    MS-Off Ver
    Excel 2010
    Posts
    86

    Re: Print Duplex

    Leith,
    I have serched all over the internet and you seem to be the only one that has addressed this issue. However after applying your code I cannot get the printer to switch to duplex or back (it stays in whatever mode it was in before I run the code). The code runs without error and I tried all three duplex settings (1-3) but no go? I am running Windows 7 and Excel 2010 - any suggestions on what it might be or trouble shooting I could do?

    Thanks,

    Tom

  4. #4
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & read 2007
    Posts
    15,979

    Re: Print Duplex

    Hello Tom,

    I will check on what the cause might be or ways we can troubleshoot it. The API has evolved some since Windows XP. The biggest change is with 64 bit Windows. However, if you were using Windows 64 the code would have failed to run.

    What printer are you using this on?
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  5. #5
    Registered User
    Join Date
    01-25-2011
    Location
    Virginia
    MS-Off Ver
    Excel 2010
    Posts
    86

    Re: Print Duplex

    Leith,

    Thanks for the quick reply. The printer is an HP 2605DN, about 4 yrs old.

    Tom
    Last edited by tom.hogan; 01-24-2012 at 10:00 PM.

  6. #6
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & read 2007
    Posts
    15,979

    Re: Print Duplex

    Hello Tom,

    Thanks for the printer info. Is this a personal printer or a networked printer?
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  7. #7
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & read 2007
    Posts
    15,979

    Re: Print Duplex

    Hello Tom,

    No need to answer the last post. The printer specs indicate it uses HP PLC (Printer Control Language) 6. It most likely is not responding to API command because it expects a PLC command to set the duplex option. I will work on some code to send the PLC command to printer. That should work for you.
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  8. #8
    Registered User
    Join Date
    01-25-2011
    Location
    Virginia
    MS-Off Ver
    Excel 2010
    Posts
    86

    Re: Print Duplex

    Leith,

    I am currently using the PCL driver but it has as a postscript driver that I could use if that would make it easier.

    Tom

  9. #9
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & read 2007
    Posts
    15,979

    Re: Print Duplex

    Hello Tom,

    Try this macro. It should send the set duplex command directly to the printer in PCL.
    'Written: January 24, 2012
    'Author:  Leith Ross
    'Summary: Sends HP PCL Simplex/Duplex commands to a printer.
    
    ' Print Spooler Win32 API Calls
    '
    Private Declare Function OpenPrinter _
      Lib "winspool.drv" Alias "OpenPrinterA" _
        (ByVal pPrinterName As String, _
         ByRef phPrn As Long, _
         ByRef pDefault As Any) As Long
         
    Private Declare Function StartDocPrinter _
      Lib "winspool.drv" Alias "StartDocPrinterA" _
        (ByVal hPrn As Long, _
         ByVal level As Long, _
         ByRef pDocInfo As DOC_INFO_1) As Long
         
    Private Declare Function StartPagePrinter _
      Lib "winspool.drv" _
        (ByVal hPrn As Long) As Long
        
    Private Declare Function WritePrinter _
      Lib "winspool.drv" _
        (ByVal hPrn As Long, _
         ByVal pBuf As String, _
         ByVal cdBuf As Long, _
         ByRef pcWritten As Long) As Long
         
    Private Declare Function EndPagePrinter _
      Lib "winspool.drv" _
        (ByVal hPrn As Long) As Long
        
    Private Declare Function EndDocPrinter _
      Lib "winspool.drv" _
        (ByVal hPrn As Long) As Long
        
    Private Declare Function ClosePrinter _
      Lib "winspool.drv" _
        (ByVal hPrn As Long) As Long
    '
    '
    ' API Structure required by StartDocPrinter
    '
    Private Type DOC_INFO_1
       pDocName As String
       pOutputFile As String
       pDatatype As String
    End Type
    '
    '
    '
    ' Steps to send raw data to a printer
    '   1. Call OpenPrinter to get a handle to the printer.
    '   2. Initialize a DOCINFO structure with the printer data.
    '   3. Call StartDocPrinter to indicate that the application will be sending document data to the printer.
    '   4. Call StartPagePrinter to indicate that the application will be sending a new page to the printer.
    '   5. Call WritePrinter to send the data.
    '   6. Call EndPagePrinter to indicate that all data for the current page has been sent.
    '   7. Call EndDocPrinter to indicate that all data for this document has been sent.
    '   8. Call ClosePrinter to release the resources.
    
    Sub SetDuplexMode()
    
      Dim BytesWritten As Long
      Dim Cmd As String
      Dim DocInfo As DOC_INFO_1
      Dim hPrn As Long
      Dim PrinterName As String
      Dim Response As Boolean
      Dim Status As Long
      
       'HP PLC Simplex and Duplex commands.
        SimplexMode = vbEsc & Chr(38) & Chr(108) & Chr(48) & Chr(83)
        DuplexLegal = vbEsc & Chr(38) & Chr(108) & Chr(49) & Chr(83)
        DuplexBook = vbEsc & Chr(38) & Chr(108) & Chr(50) & Chr(83)
        
        Cmd = DuplexBook
        
        PrinterName = Application.ActivePrinter
        PrinterName = Left(PrinterName, InStr(1, PrinterName, " on") - 1)
        
        Status = OpenPrinter(PrinterName, hPrn, ByVal 0)
        
        If Status <> 0 Then
           With DocInfo
             .pDatatype = "TEXT"
             .pDocName = "My Document"
             .pOutputFile = ""
           End With
           
           Job = StartDocPrinter(hPrn, 1, DocInfo)
           
             If Job > 0 Then
                Status = StartPagePrinter(hPrn)
                
                  If Status <> 0 Then
                     Status = WritePrinter(hPrn, Cmd, Len(Cmd), BytesWritten)
                     EndPagePrinter hPrn
                  End If
                
                EndDocPrinter hPrn
             End If
            
           ClosePrinter hPrn
        End If
        
        If BytesWritten = Len(Cmd) Then
           MsgBox "Command sent to printer was successful."
        End If
        
    End Sub
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  10. #10
    Registered User
    Join Date
    01-25-2011
    Location
    Virginia
    MS-Off Ver
    Excel 2010
    Posts
    86

    Re: Print Duplex

    Leith,
    Thanks for all the help. I have tried your macro and it runs without error. It does duplex (I can see the page go through the duplexer) but it prints a blank page. I tried setting a print range with ActiviateSheet.PageSetup.PrintArea but that did not help. I also tried changing the CMD= to SimplexMode but it still duplexes a blank sheet. I did step through the macro and the value for CMD is changing based on the CMD = line but it still duplexes. I also tried setting CMD to DuplexLegal but got the same result.

    Clearly some cmd is being sent to the printer, but it needs a little tweeking? Also, I relooked my print driver and it is PS not PCL. HP does not have a PCL driver for Windows 7.

    Regards,

    Tom

  11. #11
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & read 2007
    Posts
    15,979

    Re: Print Duplex

    Hello Tom,

    I will have to check on the Post Script method for setting the printer to duplex mode. At least we are making headway.
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  12. #12
    Registered User
    Join Date
    01-25-2011
    Location
    Virginia
    MS-Off Ver
    Excel 2010
    Posts
    86

    Re: Print Duplex

    Leith,
    I give up. I got so frustrated I went out an bought a new printer, HP CP2025dn. I did a bunch of internet research and your API code looks perfect. I also confirmed that the PCL code is correct. So i installed the new printer wiht PCL driver and tried both of your codes (plus a simular API code form MSFT site) and none of them work. I can only guess that it has something to do with the fact that I am printing to it as a network printer (static IP) but I don't understand why that would matter.

    Thanks again for your help, this may be one of those problems for which there is not a VBA solution.

    Regards,

    Tom

  13. #13
    Registered User
    Join Date
    01-25-2011
    Location
    Virginia
    MS-Off Ver
    Excel 2010
    Posts
    86

    Re: Print Duplex

    Leith,
    The plot thickens. I read else where that if you changed the printer back and forth then the duplex setting would take. This did not work for me unitl i did it twice in a row. So with your code and the below macro I can now change my printer's duplex setting:
    Sub Print_Duplex()
    
      Dim PrinterName As String
      Dim n As Integer
      
      For n = 1 To 2
        Application.ActivePrinter = "test printer on Ne07:"
        Application.ActivePrinter = "test printer1 on Ne08:"
        PrinterName = Application.ActivePrinter
        SetPrinterToDuplex Left(PrinterName, InStr(1, PrinterName, " on") - 1), 2
      Next n
           
    End Sub
    I irritates me that I don't understand why this works, but it does so I guess it's solved. I can't mark this as solved but I have rated you highly thanks for the help.

    Tom

    P.S. If you can explain why this works I would like to hear it!

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.2.0