?
Solved

Printer Selection from combo box

Posted on 2007-11-22
12
Medium Priority
?
769 Views
Last Modified: 2008-02-01
Hi

I have a annoying problem I have a form with a combo box that lists printers on a PC. in properties are the following
Data
Row Source Type        FillPrinterList    (Function call)

Format
Column Count = 4
ColumnWidth     =  ;0cm;0cm;0cm

pName = me!cboPrinter.Column(1)

Problem it works and other times I get Null Value in pName

with the pName = Me!cboPrinter.Column(1)
I have tried on exit, on focus etc

I must be doing something wrong. If some one can see the problem help would be most apprciated

chestera
0
Comment
Question by:chestera
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
  • +2
12 Comments
 
LVL 75
ID: 20337075
Hi Alan ...

Seems it would be an issue with the List fill function.  Can you post the code for that?

mx
0
 
LVL 10

Expert Comment

by:LennyGray
ID: 20337189
You specify 4 columns but you define the width for only 3.

If the first column is the name of the printer, then pName = me!cboPrinter.Column(1)
 is incorrect.

It can be stated in either of two ways:

pName = me!cboPrinter.Column(0)

or

pName = me!cboPrinter


Comboboxes are zero-based numbering (satrts at zero) for reference but the boundccolumn property starts at 1 not zero.

I hope that this helps.
0
 
LVL 75
ID: 20337211
"You specify 4 columns but you define the width for only 3"
The 4th column will be the defined by the Width of the combo box ... and the 4th column is probably a description of the printer.

Also, sounds like the printer name is in physical column 2, thus Column(1) would be correct.

mx
0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 

Author Comment

by:chestera
ID: 20337513
databasemax

I have tried (0) and (1) it seems (1) it the right column but it's erratic Works then spits the dummy and doesn't work. The complet code is quite large. I will post the FillPrinterList portion.

chestera
0
 

Author Comment

by:chestera
ID: 20337514
databasemx

Here it the FillPrintList code

' Code from:
' Microsoft Access 95 How-To
' (c) 1998 Ken Getz and Paul Litwin
' All rights reserved.

' You may only use this code as part of an application
' that requires its use. You must including this
' notice intact. You may not distribute the code
' as your own work, nor can you distribute the
' code on its own.

Function ahtGetDefaultPrinter(dr As aht_tagDeviceRec) As Boolean

   ' Retrieve the default printer information. Though
   ' the function dutifully returns True if the
   ' values were available, and False otherwise, Windows
   ' really isn't happy without a default printer, and
   ' this situation rarely comes up.

   ' In:
   '     dr: a aht_tagDeviceRec structure to fill in
   ' Out:
   '     Return Value: True if info available, False otherwise.
   '     dr: filled in with default printer information,
   '        if it was available (check the function's return
   '        value).
   '
   ' Comments:
   '     Requires the ahtGetToken() function from basGetToken
   '     Requires the ahtGetINIString() function from basINIFile
   '     Requires type definitions from basPrintTypes
   
   Dim strBuffer As String

   strBuffer = ahtGetINIString("Windows", "Device")
   If Len(strBuffer) > 0 Then
      With dr
         .drDeviceName = ahtGetToken(strBuffer, ",", 1)
         .drDriverName = ahtGetToken(strBuffer, ",", 2)
         .drPort = ahtGetToken(strBuffer, ",", 3)
      End With
      ahtGetDefaultPrinter = True
   Else
      ahtGetDefaultPrinter = False
   End If
End Function

Function ahtSetDefaultPrinter(dr As aht_tagDeviceRec) As Boolean

   ' Set the default printer device in Win.INI

   ' In:
   '     dr: a aht_tagDeviceRec structure to use as
   '        the source of information.
   ' Out:
   '     Return Value: True if set correctly, False otherwise.
   '     If successful, writes a string in the form:
   '        device=HP LaserJet 4,HPPCL5E,LPT1:
   '     to your Win.INI file.
   '
   ' Comments:
   '     Requires the aht_apiWriteProfileString() declaration from basINIFile
   '     Requires type definitions from basPrintTypes

   Dim strBuffer As String

   ' Build up the appropriate string.
   strBuffer = dr.drDeviceName & ","
   strBuffer = strBuffer & dr.drDriverName & ","
   strBuffer = strBuffer & dr.drPort

   ' Now write that string out to WIN.INI.
   ahtSetDefaultPrinter = (aht_apiWriteProfileString("Windows", _
    "Device", strBuffer) <> 0)
End Function

Private Sub TestDefaultPrinter()
   
   ' Test the ahtDefaultPrinter() function.
   ' Fill in a DeviceRec structure with
   ' the pieces of the default printer info,
   ' and then print them out.

   Dim dr As aht_tagDeviceRec
   
   If ahtGetDefaultPrinter(dr) Then
      Debug.Print "Device: "; dr.drDeviceName
      Debug.Print "Driver: "; dr.drDriverName
      Debug.Print "Port  : "; dr.drPort
   End If
End Sub
0
 
LVL 85
ID: 20338047
Albert Kallal provides a code module that helps with switching printers, and part of that code shows how to get a listing of the available printers:

http://www.members.shaw.ca/AlbertKallal/msaccess/msaccess.html
0
 
LVL 10

Expert Comment

by:LennyGray
ID: 20338255
you can easily add the printers on a custom menu and it would take literally seconds to so.

Are you trying to add a way to select printers?

I will be away for the next two days, so I would hope that one of the experts could direct this person in the method to make a custom menubar from the GUI for the printer.  




Good Luck !!
0
 
LVL 85

Accepted Solution

by:
Scott McDaniel (Microsoft Access MVP - EE MVE ) earned 2000 total points
ID: 20338680
You can also use code like this fill your combo. Simply copy/paste this code into a standard code module (name it something like basPrinters or such), then set your Combo's RowSourceType to "Value List" and the ColumnCount=3 and ColumnWidths=1;0;0. Call the EnumPrintersWinNT in your form's Load event, like this:

Private Sub Form_Load()
  EnumPrintersWinNT Me.cboPrinters
End Sub

Of course, replace "Me.cboPrinters" with the name of your combo. To "get" the name of the printer after your user selects one, use the AfterUpdate event of your combo:

Private Sub cboPrinters_AfterUpdate()
  MsgBox "You picked " & Me.cboPrinters.Column(0)
End Sub

Again, change the name to match the combo in your project.
Option Explicit
 
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2006 VBnet, Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce
'               or publish this code on any web site,
'               online service, or distribute as source
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 
Public Type PRINTER_INFO_1
   Flags As Long
   pDescription As Long
   Pane As Long
   Comment As Long
End Type
 
Public Type PRINTER_INFO_4
   pPrinterName As Long
   pServerName As Long
   Attributes As Long
End Type
 
'SIZEOFxxx are non-windows constants defined for this method
Public Const SIZEOFPRINTER_INFO_1 = 16
Public Const SIZEOFPRINTER_INFO_4 = 12
 
Public Const PRINTER_LEVEL1 = &H1
Public Const PRINTER_LEVEL4 = &H4
 
'EnumPrinters enumerates available printers,
'print servers, domains, or print providers.
Public Declare Function EnumPrinters Lib "winspool.drv" _
   Alias "EnumPrintersA" _
  (ByVal Flags As Long, _
   ByVal Name As String, _
   ByVal Level As Long, _
   pPrinterEnum As Any, _
   ByVal cbBuffer As Long, _
   pcbNeeded As Long, _
   pcReturned As Long) As Long
 
'EnumPrinters Parameters:
'Flags - Specifies the types of print objects that the function should enumerate.
Public Const PRINTER_ENUM_DEFAULT = &H1     'Windows 95: The function returns
                                            'information about the default printer.
Public Const PRINTER_ENUM_LOCAL = &H2       'function ignores the Name parameter,
                                            'and enumerates the locally installed
                                            'printers. Windows 95: The function will
                                            'also enumerate network printers because
                                            'they are handled by the local print provider
Public Const PRINTER_ENUM_CONNECTIONS = &H4 'Windows NT/2000: The function enumerates the
                                            'list of printers to which the user has made
                                            'previous connections
Public Const PRINTER_ENUM_NAME = &H8        'enumerates the printer identified by Name.
                                            'This can be a server, a domain, or a print
                                            'provider. If Name is NULL, the function
                                            'enumerates available print providers
Public Const PRINTER_ENUM_REMOTE = &H10     'Windows NT/2000: The function enumerates network
                                            'printers and print servers in the computer's domain.
                                            'This value is valid only if Level is 1
Public Const PRINTER_ENUM_SHARED = &H20     'enumerates printers that have the shared attribute.
                                            'Cannot be used in isolation; use an OR operation
                                            'to combine with another PRINTER_ENUM type
Public Const PRINTER_ENUM_NETWORK = &H40    'Windows NT/2000: The function enumerates network
                                            'printers in the computer's domain. This value is
                                            'valid only if Level is 1.
 
'''''''''''''''''''''''
'Name:
'If Level is 1, Flags contains PRINTER_ENUM_NAME, and Name is non-NULL,
'then Name is a pointer to a null-terminated string that specifies the
'name of the object to enumerate. This string can be the name of a server,
'a domain, or a print provider.
'
'If Level is 1, Flags contains PRINTER_ENUM_NAME, and Name is NULL, then
'the function enumerates the available print providers.
'
'If Level is 1, Flags contains PRINTER_ENUM_REMOTE, and Name is NULL, then
'the function enumerates the printers in the user's domain.
'
'If Level is 2 or 5, Name is a pointer to a null-terminated string that
'specifies the name of a server whose printers are to be enumerated. If
'this string is NULL, then the function enumerates the printers installed
'on the local machine.
'
'If Level is 4, Name should be NULL. The function always queries on
'the local machine.
 
'When Name is NULL, it enumerates printers that are installed on the
'local machine. These printers include those that are physically attached
'to the local machine as well as remote printers to which it has a
'network connection.
 
'''''''''''''''''''''''
'Level:
'Specifies the type of data structures pointed to by pPrinterEnum.
'Valid values are 1, 2, 4, and 5, which correspond to the
'PRINTER_INFO_1, PRINTER_INFO_2, PRINTER_INFO_4, and PRINTER_INFO_5
'data structures.
'
'Windows 95: The value can be 1, 2, or 5.
'
'Windows NT/Windows 2000: This value can be 1, 2, 4, or 5.
 
'''''''''''''''''''''''
'pPrinterEnum:
'Pointer to a buffer that receives an array of PRINTER_INFO_1,
'PRINTER_INFO_2, PRINTER_INFO_4, or PRINTER_INFO_5 structures.
'Each structure contains data that describes an available print object.
'
'If Level is 1, the array contains PRINTER_INFO_1 structures.
'If Level is 2, the array contains PRINTER_INFO_2 structures.
'If Level is 4, the array contains PRINTER_INFO_4 structures.
'If Level is 5, the array contains PRINTER_INFO_5 structures.
'
'The buffer must be large enough to receive the array of data
'structures and any strings or other data to which the structure
'members point. If the buffer is too small, the pcbNeeded parameter
'returns the required buffer size.
'
'Windows 95: The buffer cannot receive PRINTER_INFO_4 structures.
'It can receive any of the other types.
 
'''''''''''''''''''''''
'cbBuf
'Specifies the size, in bytes, of the buffer pointed to by pPrinterEnum.
'''''''''''''''''''''''
'pcbNeeded
'Pointer to a value that receives the number of bytes copied if the
'function succeeds or the number of bytes required if cbBuffer is too small.
'''''''''''''''''''''''
'pcReturned
'Pointer to a value that receives the number of PRINTER_INFO_1,
'PRINTER_INFO_2, PRINTER_INFO_4, or PRINTER_INFO_5 structures that
'the function returns in the array to which pPrinterEnum points.
 
 
'PRINTER_INFO_4 returned Attribute values
Public Const PRINTER_ATTRIBUTE_DEFAULT = &H4
Public Const PRINTER_ATTRIBUTE_DIRECT = &H2
Public Const PRINTER_ATTRIBUTE_ENABLE_BIDI = &H800&
Public Const PRINTER_ATTRIBUTE_LOCAL = &H40
Public Const PRINTER_ATTRIBUTE_NETWORK = &H10
Public Const PRINTER_ATTRIBUTE_QUEUED = &H1
Public Const PRINTER_ATTRIBUTE_SHARED = &H8
Public Const PRINTER_ATTRIBUTE_WORK_OFFLINE = &H400
 
'PRINTER_INFO_1 returned Flag values
Public Const PRINTER_ENUM_CONTAINER = &H8000&
Public Const PRINTER_ENUM_EXPAND = &H4000
Public Const PRINTER_ENUM_ICON1 = &H10000
Public Const PRINTER_ENUM_ICON2 = &H20000
Public Const PRINTER_ENUM_ICON3 = &H40000
Public Const PRINTER_ENUM_ICON4 = &H80000
Public Const PRINTER_ENUM_ICON5 = &H100000
Public Const PRINTER_ENUM_ICON6 = &H200000
Public Const PRINTER_ENUM_ICON7 = &H400000
Public Const PRINTER_ENUM_ICON8 = &H800000
 
Public Const LB_SETTABSTOPS As Long = &H192
 
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
  (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   lParam As Any) As Long
   
Public Declare Function lstrcpyA Lib "kernel32" _
  (ByVal RetVal As String, ByVal ptr As Long) As Long
                        
Public Declare Function lstrlenA Lib "kernel32" _
  (ByVal ptr As Any) As Long
  
Private Declare Function SetDefaultWindowsPrinter Lib "winspool.drv" _
   Alias "SetDefaultPrinterA" _
  (ByVal pszPrinter As String) As Long
 
Function GetStrFromPtrA(ByVal lpszA As Long) As String
 
   GetStrFromPtrA = String$(lstrlenA(ByVal lpszA), 0)
   Call lstrcpyA(ByVal GetStrFromPtrA, ByVal lpszA)
   
End Function
 
 
Public Function SetAsDefaultPrinter(PrinterName As String) As Boolean
'/Purpose:
'/Parameters:
'/    PrinterName
'/Returns: Boolean
'/Created: 3/6/2007
'/Created By: Scott
 
 
  Dim i       As Integer
  Dim blnSet  As Boolean
 
On Error GoTo Err_SetAsDefaultPrinter
 
    For i = 0 To Application.Printers.Count - 1
        If Application.Printers(i).DeviceName = PrinterName Then
          Set Application.Printer = Application.Printers(i)
          blnSet = True
          Exit For
        End If 'If Application.Printers(i).DeviceName = PrinterName
    Next i
 
  SetAsDefaultPrinter = blnSet
 
Exit_SetAsDefaultPrinter:
  On Error Resume Next
  Exit Function
 
Err_SetAsDefaultPrinter:
  Select Case Err
    'case
    'case
    Case Else
     MsgBox Err & ":" & Error$, vbCritical, "basPrinters" & ": " & "SetAsDefaultPrinter"
  End Select
  
  Resume Exit_SetAsDefaultPrinter
 
End Function
 
 
Public Function IsPrinterAvailable(PrinterName As String) As Boolean
  '/Purpose:
  '/Parameters:
  '/    PrinterName
  '/Returns: Boolean
  '/Created: 3/5/2007
  '/Created By: Scott
 
  Dim cbRequired  As Long
  Dim cbBuffer    As Long
  Dim ptr()       As PRINTER_INFO_4
  Dim nEntries    As Long
  Dim cnt         As Long
 
  On Error GoTo Err_IsPrinterAvailable
 
  Call EnumPrinters(PRINTER_ENUM_CONNECTIONS Or PRINTER_ENUM_LOCAL, _
  vbNullString, PRINTER_LEVEL4, _
  0, 0, cbRequired, nEntries)
   
  ReDim ptr((cbRequired \ SIZEOFPRINTER_INFO_4))
  cbBuffer = cbRequired
    
  'Enumerate the printers. If the function succeeds,
  'the return value is nonzero. If the function fails,
  'the return value is zero.
    If EnumPrinters(PRINTER_ENUM_CONNECTIONS Or PRINTER_ENUM_LOCAL, _
      vbNullString, PRINTER_LEVEL4, _
      ptr(0), cbBuffer, _
      cbRequired, nEntries) Then
              
        For cnt = 0 To nEntries - 1
           
            With ptr(cnt)
              '/If GetStrFromPtrA(.pPrinterName) = "hp LaserJet 1000" Then Stop
                If PrinterName = GetStrFromPtrA(.pPrinterName) Then
                  IsPrinterAvailable = True
                  Exit For
                End If 'If PrinterName = GetStrFromPtrA(.pPrinterName)
            End With
              
        Next cnt
    End If 'If EnumPrinters(PRINTER_ENUM_CONNECTIONS Or PRINTER_ENUM_LOCAL,vbNullString, PRINTER_LEVEL4,ptr(0), cbBuffer,cbRequired, nEntries)
 
Exit_IsPrinterAvailable:
  On Error Resume Next
  Erase ptr
  Exit Function
 
Err_IsPrinterAvailable:
    Select Case Err
      'case
      'case
      Case Else
        MsgBox Err & ":" & Error$, vbCritical, "basPrinters" & ": " & "IsPrinterAvailable"
    End Select
  
  
  Resume Exit_IsPrinterAvailable
 
End Function
 
 Function EnumPrintersWinNT(ctl As ComboBox) As Long
    
   Dim Success As Boolean
   Dim cbRequired As Long
   Dim cbBuffer As Long
   Dim ptr() As PRINTER_INFO_4
   Dim nEntries As Long
   Dim cnt As Long
   Dim sAttr As String
   
   ctl.RowSource = ""
   
  'To determine the required buffer size, call EnumPrinters with
  'cbBuffer set to zero. EnumPrinters fails, and Err.LastDLLError
  'returns ERROR_INSUFFICIENT_BUFFER, filling in the cbRequired
  'parameter with the size, in bytes, of the buffer required to
  'hold the array of structures and their data.
   
   Call EnumPrinters(PRINTER_ENUM_CONNECTIONS Or PRINTER_ENUM_LOCAL, _
                     vbNullString, PRINTER_LEVEL4, _
                     0, 0, cbRequired, nEntries)
            
   
  'The strings pointed to by each PRINTER_INFO_4 struct's members
  'reside in memory after the end of the array of structs. So we're
  'not only allocating memory for the structs themselves, but all the
  'strings pointed to by each struct's member as well.
   ReDim ptr((cbRequired \ SIZEOFPRINTER_INFO_4))
       
  'Set cbBuffer equal to the size of the buffer
   cbBuffer = cbRequired
    
  'Enumerate the printers. If the function succeeds,
  'the return value is nonzero. If the function fails,
  'the return value is zero.
   If EnumPrinters(PRINTER_ENUM_CONNECTIONS Or PRINTER_ENUM_LOCAL, _
                   vbNullString, PRINTER_LEVEL4, _
                   ptr(0), cbBuffer, _
                   cbRequired, nEntries) Then
              
      For cnt = 0 To nEntries - 1
           
         With ptr(cnt)
            
            '/If GetStrFromPtrA(.pPrinterName) = "hp LaserJet 1000" Then Stop
            
            sAttr = ""
               
            If (.Attributes And PRINTER_ATTRIBUTE_DEFAULT) Then sAttr = "default "
            If (.Attributes And PRINTER_ATTRIBUTE_DIRECT) Then sAttr = sAttr & "direct "
            If (.Attributes And PRINTER_ATTRIBUTE_ENABLE_BIDI) Then sAttr = sAttr & "bidirectional "
            If (.Attributes And PRINTER_ATTRIBUTE_LOCAL) Then sAttr = sAttr & "local "
            If (.Attributes And PRINTER_ATTRIBUTE_NETWORK) Then sAttr = sAttr & "net "
            If (.Attributes And PRINTER_ATTRIBUTE_QUEUED) Then sAttr = sAttr & "queued "
            If (.Attributes And PRINTER_ATTRIBUTE_SHARED) Then sAttr = sAttr & "shared "
            If (.Attributes And PRINTER_ATTRIBUTE_WORK_OFFLINE) Then sAttr = sAttr & "offline "
            
            ctl.AddItem GetStrFromPtrA(.pPrinterName) & ";" & _
                        GetStrFromPtrA(.pServerName) & ";" & _
                        sAttr
 
         End With
              
      Next cnt
        
   Else
      ctl.AddItem "Error enumerating printers."
   End If  'EnumPrinters
   
   EnumPrintersWinNT = nEntries
    
End Function

Open in new window

0
 
LVL 75
ID: 20339923
Actually, I've never seen the need for the various code over the years for selecting printers.  If you bring up any report in print preview, you can right click (or use the File menu) and you have available (built in) the Print ... and Page Setup menus. From these dialogs, the use can select any printer that is installed and set other properties for either the printer and/or the page. In addition, you can create your own right click menu with further added functionality.  

I suppose the code might be necessary if ... you were not using print preview and needed to go directly to a specific printer.  I alway use print preview ... before shooting a load of paper out to a printer blindly.

mx
0
 

Author Comment

by:chestera
ID: 20340426
databasemx

Office 2003 no longer supports Print dialog box in mail merge sendto printer. I need to select printer Number of copies and tray so I designed a smiple dialog box

 WordDoc.Application.ActivePrinter = pName
   WordDoc.Application.PrintOut Copies:=nCopies
   With Options
        .DefaultTray = "Tray" & nTray
   End With

I have since found via lsmconsulting I don't need this massive code I am currently using.

chestera




0
 

Author Comment

by:chestera
ID: 20340874
lmsconsulting

I modified using your code now working 100%. problem with my code it wouldn't always populate variable pName from the combo box from time to time I would get invalid use of null. I think it might be how the combo box was set up. Anyway thanks for that code

chestera
0
 

Expert Comment

by:mytfein
ID: 26546552
Hi Gentlemen,

If you have a few minutes,

Just posted a related question here:
     http://www.experts-exchange.com/Microsoft/Development/MS_Access/Q_25135122.html

Would LSM's solution work for my situation?
If so your help would be appreciated, bec. i do not know how to use the code.
tx, sandra
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

As tax season makes its return, so does the increase in cyber crime and tax refund phishing that comes with it
Code that checks the QuickBooks schema table for non-updateable fields and then disables those controls on a form so users don't try to update them.
Learn how to number pages in an Access report over each group. Activate two pass printing by referencing the pages property: Add code to the Page Footers OnFormat event to capture the pages as there occur for each group. Use the pages property to …
In Microsoft Access, learn how to use Dlookup and other domain aggregate functions and one method of specifying a string value within a string. Specify the first argument, which is the expression to be returned: Specify the second argument, which …
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question