Printer Location and Model

Posted on 2005-05-11
Last Modified: 2008-01-09
I am trying to figure out how i can populate a drop down with the printer device name in column 1 (i know how to do from before here) and location & " - " & model in column 2, either from the printers on that machine (local or not) or all of the printers available over the network. (VBA of Course)
Question by:Y2Kingswood
    LVL 74

    Expert Comment

    by:Jeffrey Coachman
    This information is covered in depth in the "Access Developers Handbook", Desktop Edition

    (In the Access 2000 version it is chapter 10.)

    Hope this helps

    Author Comment

    Where would i find this "Access Developers Handbook"?
    LVL 74

    Expert Comment

    by:Jeffrey Coachman

    Yeah, the name makes you think it is some kind of proprietary publication. But you can actually find it in any large bookstore or on-line.

    Here are two links:

    Barnes and Noble:

    There are actually two books one is "Desktop" and the other is "Enterprise".
    I refered to the "Desktop" version of the book.

    Try to buy the version of the book that is specific to your version of Access.

    Author Comment

    you couldnt possible give me a snippet of code to save me 50 odd dollars?
    LVL 74

    Expert Comment

    by:Jeffrey Coachman
    In Access 2000 (The version I have) it is not a "Snippet".

    It's about a hundred lines of code! (Very confusing stuff)

    In Access 2002, the printer Object is more "Exposed" to Visual Basic than it was Access 2000 or 97.

    But again, I have the 2000 version of the book. I only read through the code once, just to see if I wanted to be bothered. But it turned out not to be worth it at that time. I never used it.

    I hear, (but I don't kow for sure) that the code in 2002 and 2003 is a lot simpler (About 10 lines!)
    (It probably involves looping through the "Printers" collection and loading the name of each Printer in the combobox)

    With that in mind, You could probably do a search on Google and find it! Something like:
    Access 2002 Printer Selection Dropdown ComboBox

    Or even go down to your local book store and "Read" the code

    I do that all the time. I'm cheap too!

    (BTW: it is a GREAT book anyway, (well worth the $50) every Access developer has it on their shelf.)

    Hope this helps.
    LVL 15

    Expert Comment

    Hi Y2Kingswood,

    I'm not an expert here and didn't try it, but there is some code here:
    I see PRINTER_INFO_2 has pLocation member.
    Merrion who wrote that is also expert on EE, he's active in VB topic area, maybe you should ask there.

    LVL 74

    Expert Comment

    by:Jeffrey Coachman

    Besides there is probably some "Nerdy" legal reason why we can't just Post Copyrighted, Published code here. (Need permission from the Author, Copyright infringement, Plagerism, Fair Use, .... bla ... bla ...bla


    Author Comment

    hehe true true. ill try these sugestions out
    LVL 2

    Accepted Solution

    You will probably need to dip into the API to get this information.  GetPrinter with PRINTER_INFO_2 is your best bet....

    Private Type PRINTER_INFO_2
        pServerName As String
        pPrinterName As String
        pShareName As String
        pPortName As String
        pDriverName As String
        pComment As String
        pLocation As String
        pDevMode As Long 'LPDEVMODEA
        pSepFile As String
        pPrintProcessor As String
        pDatatype As String
        pParameters As String
        pSecurityDescriptor As Long 'PSECURITY_DESCRIPTOR
        Attributes As Long
        Priority As Long
        DefaultPriority As Long
        StartTime As Long
        UntilTime As Long
        Status As Long
        JobsCount As Long
        AveragePPM As Long
    End Type

    Private Declare Function GetPrinterApi Lib "winspool.drv" Alias _
                               "GetPrinterA" (ByVal hPrinter As Long, _
                                                ByVal Level As Long, _
                                                buffer As Long, _
                                                ByVal pbSize As Long, _
                                                pbSizeNeeded As Long) As Long

    Private Declare Function OpenPrinter Lib "winspool.drv" _
            Alias "OpenPrinterA" (ByVal pPrinterName As String, _
            phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long

    Private Declare Function ClosePrinter Lib "winspool.drv" _
            (ByVal hPrinter As Long) As Long

      pDatatype As String
      pDevMode As Long
      DesiredAccess As Long
    End Type

    '\\ Pointer validation in StringFromPointer
    Private Declare Function IsBadStringPtrByLong Lib "kernel32" Alias "IsBadStringPtrA" (ByVal lpsz As Long, ByVal ucchMax As Long) As Long

    Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long
    Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As Long, ByVal lpString2 As String) As Long
    Private Declare Function lstrcpyToBuffer Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As Long) As Long

    Private Function GetPrinterLocation(Byval DeviceName As String ) As String

    Dim lRet As Long
    Dim SizeNeeded As Long
    Dim buffer() As Long
    Dim mhPrinter As Long '\\Printer handle...must close after use.

    lRet = OpenPrinter(Devicename, mhPrinter, pDef)

    If mhPrinter <> 0 Then
      ReDim Preserve buffer(0 To 1) As Long
      lRet = GetPrinterApi(mhPrinter, Index, buffer(0), UBound(buffer), SizeNeeded)
      ReDim Preserve buffer(0 To (SizeNeeded / 4) + 3) As Long
      lRet = GetPrinterApi(mhPrinter, Index, buffer(0), UBound(buffer) * 4, SizeNeeded)

            With mPRINTER_INFO_2
                .pServerName = StringFromPointer(buffer(0), 1024)
                .pPrinterName = StringFromPointer(buffer(1), 1024)
                .pShareName = StringFromPointer(buffer(2), 1024)
                .pPortName = StringFromPointer(buffer(3), 1024)
                .pDriverName = StringFromPointer(buffer(4), 1024)
                .pComment = StringFromPointer(buffer(5), 1024)
                .pLocation = StringFromPointer(buffer(6), 1024)
                .pDevMode = buffer(7)
                .pSepFile = StringFromPointer(buffer(8), 1024)
                .pPrintProcessor = StringFromPointer(buffer(9), 1024)
                .pDatatype = StringFromPointer(buffer(10), 1024)
                .pParameters = StringFromPointer(buffer(11), 1024)
                .pSecurityDescriptor = buffer(12)
                .Attributes = buffer(13)
                .Priority = buffer(14)
                .DefaultPriority = buffer(15)
                .StartTime = buffer(16)
                .UntilTime = buffer(17)
                .Status = buffer(18)
                .JobsCount = buffer(19)
                .AveragePPM = buffer(20)
            End With
           GetPrinterLocation = mPRINTER_INFO_2.pLocation
           Call ClosePrinter(mhPrinter)
      GetPrinterLocation = "Printer " & Devicename & " not found"
    End If

    End Function

    '\\ --[StringFromPointer]-------------------------------------------------------------------
    '\\ Returns a VB string from an API returned string pointer
    '\\ Parameters:
    '\\   lpString - The long pointer to the string
    '\\   lMaxlength - the size of empty buffer to allow
    '\\ HISTORY:
    '\\  DEJ 28/02/2001 Check pointer is a valid string pointer...
    '\\ ----------------------------------------------------------------------------------------
    '\\ (c) 2001 - Merrion Computing.  All rights  to use, reproduce or publish this code reserved
    '\\ Please check for updates.
    '\\ ----------------------------------------------------------------------------------------
    Public Function StringFromPointer(lpString As Long, lMaxLength As Long) As String

    Dim sRet As String
    Dim lRet As Long

    If lpString = 0 Then
        StringFromPointer = ""
        Exit Function
    End If

    lRet = lstrlen(lpString)
    If lRet < lMaxLength Then
        lMaxLength = lRet
    End If

    If IsBadStringPtrByLong(lpString, lMaxLength) Then
        '\\ An error has occured - do not attempt to use this pointer
        Debug.Print "StringFromPointer - Attempt to read bad string pointer: " & lpString
        StringFromPointer = ""
        Exit Function
    End If

    '\\ Pre-initialise the return string...
    sRet = Space$(lMaxLength)
    Call lstrcpyToBuffer(sRet, lpString)
    If Err.LastDllError = 0 Then
        If InStr(sRet, Chr$(0)) > 0 Then
            sRet = Left$(sRet, InStr(sRet, Chr$(0)) - 1)
        End If
    End If

    StringFromPointer = sRet

    End Function

    This is a cut-and-paste job so some declarations might be missing...let me know if there are...

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Top 6 Sources for Identifying Threat Actor TTPs

    Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

    Suggested Solutions

    QuickBooks® has a great invoice interface that we were happy with for a while but that changed in 2001 through no fault of Intuit®. Our industry's unit names are dictated by RUS: the Rural Utilities Services division of USDA. Contracts contain un…
    Introduction The Visual Basic for Applications (VBA) language is at the heart of every application that you write. It is your key to taking Access beyond the world of wizards into a world where anything is possible. This article introduces you to…
    Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
    Familiarize people with the process of retrieving data from SQL Server using an Access pass-thru query. Microsoft Access is a very powerful client/server development tool. One of the ways that you can retrieve data from a SQL Server is by using a pa…

    758 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

    Need Help in Real-Time?

    Connect with top rated Experts

    10 Experts available now in Live!

    Get 1:1 Help Now