Results 1 to 14 of 14
  1. #1
    4 Star Lounger
    Join Date
    Jan 2001
    Location
    Tacoma, Washington, USA
    Posts
    406
    Thanks
    0
    Thanked 1 Time in 1 Post

    Identifying printer bin names and Word 2010

    Early this year with the help I found ->here I was able to create a macro that looked at the user's active printer and gave them options for selecting the designed tray or bin. Below is my code.

    It works perfectly on my computers with Word 2007. It doesn't, however, work on computers running Word 2010. It gives me this error: Run-time error '5': Invalid procedure call or argument

    The debug says the problem is on this line number 65:

    sNamesList = String(24 * iBins, 0)

    Something much have changed in Word 2010. Is it a problem with the 24 char size? Do I need to change that? Do I need to do something completely different to achieve what I need?

    Code:
    Option Explicit
      
    Private Const DC_BINS = 6
    Private Const DC_BINNAMES = 12
        
    Private Declare Function DeviceCapabilities Lib "winspool.drv" _
        Alias "DeviceCapabilitiesA" (ByVal lpDeviceName As String, _
        ByVal lpPort As String, ByVal iIndex As Long, lpOutput As Any, _
        ByVal dev As Long) As Long
    
    
    Public Function GetBinNumbers() As Variant
    
    
        'Code adapted from Microsoft KB article Q194789
        'HOWTO: Determine Available PaperBins with DeviceCapabilities API
        Dim iBins As Long
        Dim iBinArray() As Integer
        Dim sPort As String
        Dim sCurrentPrinter As String
    
    
        'Get the printer & port name of the current printer
        sPort = Trim$(Mid$(ActivePrinter, InStrRev(ActivePrinter, " ") + 1))
        sCurrentPrinter = Trim$(Left$(ActivePrinter, _
            InStr(ActivePrinter, " on ")))
    
    
        'Find out how many printer bins there are
        iBins = DeviceCapabilities(sCurrentPrinter, sPort, _
            DC_BINS, ByVal vbNullString, 0)
    
    
        'Set the array of bin numbers to the right size
        ReDim iBinArray(0 To iBins - 1)
    
    
        'Load the array with the bin numbers
        iBins = DeviceCapabilities(sCurrentPrinter, sPort, _
        DC_BINS, iBinArray(0), 0)
    
    
        'Return the array to the calling routine
        GetBinNumbers = iBinArray
    End Function
    
    
    Public Function GetBinNames() As Variant
        
        'Code adapted from Microsoft KB article Q194789
        'HOWTO: Determine Available PaperBins with DeviceCapabilities API
    
    
        Dim iBins As Long
        Dim ct As Long
        Dim sNamesList As String
        Dim sNextString As String
        Dim sPort As String
        Dim sCurrentPrinter As String
        Dim vBins As Variant
    
    
        'Get the printer & port name of the current printer
        sPort = Trim$(Mid$(ActivePrinter, InStrRev(ActivePrinter, " ") + 1))
        sCurrentPrinter = Trim$(Left$(ActivePrinter, _
            InStr(ActivePrinter, " on ")))
    
    
        'Find out how many printer bins there are
        iBins = DeviceCapabilities(sCurrentPrinter, sPort, _
            DC_BINS, ByVal vbNullString, 0)
    
    
        'Set the string to the right size to hold all the bin names
        '24 chars per name
        sNamesList = String(24 * iBins, 0)
    
    
        'Load the string with the bin names
        iBins = DeviceCapabilities(sCurrentPrinter, sPort, _
            DC_BINNAMES, ByVal sNamesList, 0)
    
    
        'Set the array of bin names to the right size
        ReDim vBins(0 To iBins - 1)
        For ct = 0 To iBins - 1
            'Get each bin name in turn and assign to the next item in the array
            sNextString = Mid(sNamesList, 24 * ct + 1, 24)
            vBins(ct) = Left(sNextString, InStr(1, sNextString, Chr(0)) - 1)
        Next ct
    
    
        'Return the array to the calling routine
        GetBinNames = vBins
    End Function
    
    
    Private Sub ContinueButton_Click()
    
    
    Dim vBinNumbers As Variant
    If ListBox1.ListIndex >= 0 Then
        vBinNumbers = GetBinNumbers
        ActiveDocument.PageSetup.FirstPageTray = _
            vBinNumbers(ListBox1.ListIndex)
    Else
        MsgBox "No paper tray has been selected."
    End If
    
    
    If ListBox2.ListIndex >= 0 Then
        vBinNumbers = GetBinNumbers
        ActiveDocument.PageSetup.OtherPagesTray = _
            vBinNumbers(ListBox2.ListIndex)
    Else
        MsgBox "No paper tray has been selected."
    End If
        
    If OptionYes1 = True Then
        If OptionOne = True Then
        Application.PrintOut Copies:=1
        End If
        If OptionTwo = True Then
        Application.PrintOut Copies:=2
        End If
        If OptionThree = True Then
        Application.PrintOut Copies:=3
        End If
        Unload frmPrint3Tray
    End If
    If OptionNo2 = True Then
        MsgBox "Done", vbOKOnly
        Unload frmPrint3Tray
    End If
    End Sub
    
    
    Private Sub UserForm_Initialize()
        ListBox1.List = GetBinNames
        ListBox2.List = GetBinNames
    End Sub
    
    
    Private Sub UserForm_Click()
        frmPrint3Tray.Hide
    End Sub
    Daisy

  2. #2
    Super Moderator RetiredGeek's Avatar
    Join Date
    Mar 2004
    Location
    Manning, South Carolina
    Posts
    6,158
    Thanks
    200
    Thanked 781 Times in 715 Posts
    Daisy,

    What version of Word 32 or 64 bit?
    What version of Windows 7/Vista 32 or 64 Bits?
    Have you tried placing a break point on the offending statement and checking to see if iBins is getting a value?
    Have you checked your function definition for DeviceCapabilities to make sure it is the correct bitness?

    Unfortunately, you didn't supply enough code to be testable.
    May the Forces of good computing be with you!

    RG

    VBA Rules!

    My Systems: Desktop Specs
    Laptop Specs


  3. #3
    4 Star Lounger
    Join Date
    Jan 2001
    Location
    Tacoma, Washington, USA
    Posts
    406
    Thanks
    0
    Thanked 1 Time in 1 Post
    One of the Windows 7 workstations is OS 32bit and other OS 64bit. Both are using the same version of Word 2010, Version 14.0.6123.5001 32bit.

    Here are the combinations where the macro *does* work: (a) Windows XP Professional 32bit computers with Word 2007, (b) Vista 32bit with Word 2007, (c) Windows 2008 Standard SP2 32bit/XenApp 5 with Word 2007, and Windows 2000 Professional with Word 2000.

    ->Here's something I found from someone who's having the same problem with Word 2010 and Windows 7. His last post says, "...it turned out instead of passing in a LONG I should have been passing in an INTEGER. Word 2010 must be more sensitive to the datatype." Is this the answer? How would I go about this? FYI, I'm a vb newb.

    As for code, the only code I didn't include was the module that calls the form. The code above is all of the code in the form.
    Daisy

  4. #4
    Super Moderator
    Join Date
    Jan 2001
    Location
    Melbourne, Victoria, Australia
    Posts
    3,514
    Thanks
    3
    Thanked 143 Times in 136 Posts
    If that is the problem, the fix is as simple as changing the dimensioning statements (which are in two different functions) to replace the word Long with Integer

    Dim iBins As Long

    becomes

    Dim iBins as Integer
    Andrew Lockton, Chrysalis Design, Melbourne Australia

  5. #5
    4 Star Lounger
    Join Date
    Jan 2001
    Location
    Tacoma, Washington, USA
    Posts
    406
    Thanks
    0
    Thanked 1 Time in 1 Post
    There must be something more because changing iBins from Long to Integer still gives me the same error on the same line. Maybe the answer is in ->this MS article.
    Daisy

  6. #6
    5 Star Lounger kmurdock's Avatar
    Join Date
    Feb 2003
    Location
    Pacific Grove, California, USA
    Posts
    667
    Thanks
    3
    Thanked 19 Times in 18 Posts
    Daisy, this same thing happened to me.

    I don't think it's that line of code, I think iBins is not being set accurately because of an issue setting the sCurrentPrinter variable.

    I changed this code (a couple of lines above):
    Code:
    sCurrentPrinter = Trim$(Left$(ActivePrinter, InStr(ActivePrinter, " on ")))
    to this:
    Code:
    sCurrentPrinter = ActivePrinter
    ... and it worked. Does that help you?

    Best,
    Kim

  7. #7
    4 Star Lounger
    Join Date
    Jan 2001
    Location
    Tacoma, Washington, USA
    Posts
    406
    Thanks
    0
    Thanked 1 Time in 1 Post
    Good news is it does work now with Word 2010. Bad news is it doesn't work now in Word 2007. Now I get that same error only with the latter version. How frustrating. Is there code I can add that would identity which version the user has and then run that line one way for Word 2007 and the other way for Word 2010?
    Daisy

  8. #8
    5 Star Lounger kmurdock's Avatar
    Join Date
    Feb 2003
    Location
    Pacific Grove, California, USA
    Posts
    667
    Thanks
    3
    Thanked 19 Times in 18 Posts
    Ah. I got around that with a little If/End If code:

    If Application.Version = "14.0" Then
    'Set sCurrentPrinter for 2010
    Else
    'Set sCurrentPrinter for 2007 and earlier
    End If

    Best, Kim

  9. #9
    Super Moderator RetiredGeek's Avatar
    Join Date
    Mar 2004
    Location
    Manning, South Carolina
    Posts
    6,158
    Thanks
    200
    Thanked 781 Times in 715 Posts
    Kim,

    Would you mind posting your final code?
    May the Forces of good computing be with you!

    RG

    VBA Rules!

    My Systems: Desktop Specs
    Laptop Specs


  10. #10
    5 Star Lounger kmurdock's Avatar
    Join Date
    Feb 2003
    Location
    Pacific Grove, California, USA
    Posts
    667
    Thanks
    3
    Thanked 19 Times in 18 Posts
    Sure RG, here it is...

    Replace the line of code that currently reads this:
    Code:
    sCurrentPrinter = Trim$(Left$(ActivePrinter, _
            InStr(ActivePrinter, " on ")))
    with this:
    Code:
    'check for Version of Word and set sCurrentPrinter accordingly
    If Application.Version = "14.0" Then
        sCurrentPrinter = ActivePrinter
    Else
        sCurrentPrinter = Trim$(Left$(ActivePrinter, _
            InStr(ActivePrinter, " on ")))
    End If
    Best, Kim
    Last edited by kmurdock; 2012-10-04 at 21:33. Reason: Hit the post button before I was ready!

  11. #11
    Super Moderator RetiredGeek's Avatar
    Join Date
    Mar 2004
    Location
    Manning, South Carolina
    Posts
    6,158
    Thanks
    200
    Thanked 781 Times in 715 Posts
    Kim,

    Thanks.
    May the Forces of good computing be with you!

    RG

    VBA Rules!

    My Systems: Desktop Specs
    Laptop Specs


  12. #12
    4 Star Lounger
    Join Date
    Jan 2001
    Location
    Tacoma, Washington, USA
    Posts
    406
    Thanks
    0
    Thanked 1 Time in 1 Post
    Perfect! The only change I might make at some point would be to change = to >= to cover future versions of Word, assuming the same code works for them as does for Word 2010. Thank you so much! You really made my week.
    Daisy

  13. #13
    5 Star Lounger kmurdock's Avatar
    Join Date
    Feb 2003
    Location
    Pacific Grove, California, USA
    Posts
    667
    Thanks
    3
    Thanked 19 Times in 18 Posts
    You are welcome. And points well taken about future versions.

    Have a great weekend.

    Best, Kim
    Last edited by kmurdock; 2012-10-05 at 16:08.

  14. #14
    5 Star Lounger kmurdock's Avatar
    Join Date
    Feb 2003
    Location
    Pacific Grove, California, USA
    Posts
    667
    Thanks
    3
    Thanked 19 Times in 18 Posts
    Quote Originally Posted by ailios View Post
    The only change I might make at some point would be to change = to >= to cover future versions of Word, assuming the same code works for them as does for Word 2010.
    FYI, 2013 (15.0) works the same as 2010. I changed the first "If" to:
    Code:
    If Application.Version >= "14.0" Then
    and it worked fine.
    Best, Kim

Posting Permissions

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