[AccessD] A97. Reportwithprinterandpaperselectionpickswrongpaper when deployed on identica

Steve Conklin (Developer@UltraDNT) Developer at UltraDNT.com
Wed Feb 9 08:26:12 CST 2005


Hey, Gustav.
I found the code I used, from msdn, but it doesn't use registry
directly, it gets the paper numbers through an API call. The sub is
"GetPaperList", but this code uses the Printer object, which is only
good on AXP+.  You'll have to work around that.

hth
Steve

>>>> begin msdn code:
Option Compare Database
Option Explicit

' Declaration for the DeviceCapabilities function API call.
Private Declare Function DeviceCapabilities Lib "winspool.drv" _
    Alias "DeviceCapabilitiesA" (ByVal lpsDeviceName As String, _
    ByVal lpPort As String, ByVal iIndex As Long, lpOutput As Any, _
    ByVal lpDevMode As Long) As Long
    
' DeviceCapabilities function constants.
Private Const DC_PAPERNAMES = 16
Private Const DC_PAPERS = 2
Private Const DC_BINNAMES = 12
Private Const DC_BINS = 6
Private Const DEFAULT_VALUES = 0

Sub ShowPrinters()
    Dim strCount As String
    Dim strMsg As String
    Dim prtLoop As Printer
    
    On Error GoTo ShowPrinters_Err

    If Printers.Count > 0 Then
        ' Get count of installed printers.
        strMsg = "Printers installed: " & Printers.Count & vbCrLf &
vbCrLf
    
        ' Enumerate printer system properties.
        For Each prtLoop In Application.Printers
            With prtLoop
                strMsg = strMsg _
                    & "Device name: " & .DeviceName & vbCrLf _
                    & "Driver name: " & .DriverName & vbCrLf _
                    & "Port: " & .Port & vbCrLf & vbCrLf
            End With
        Next prtLoop
    
    Else
        strMsg = "No printers are installed."
    End If
    
    ' Display printer information
    MsgBox Prompt:=strMsg, Buttons:=vbOKOnly, Title:="Installed
Printers"
    
ShowPrinters_End:
    Exit Sub
    
ShowPrinters_Err:
    MsgBox Prompt:=Err.Description, Buttons:=vbCritical & vbOKOnly, _
        Title:="Error Number " & Err.Number & " Occurred"
    Resume ShowPrinters_End
    
End Sub

Sub ChangeBins()
    Dim strReportName As String
    Dim prt As Printer
         
    On Error GoTo ChangeBins_Err
    
    strReportName = "Alphabetical List Of Products"
       
    'Open the report in print preview
    DoCmd.OpenReport ReportName:=strReportName, View:=acViewPreview
    
    ' Get the Printer object for the report.
    Set prt = Reports(strReportName).Printer
    
    ' Change the PaperBin property to print from the lower bin.
    prt.PaperBin = acPRBNLower

    ' Use the PrintOut method to print only the first page of the
report.
    DoCmd.PrintOut PrintRange:=acPages, PageFrom:=1, PageTo:=1
       
    ' Change the PaperBin property to print from the upper bin.
    prt.PaperBin = acPRBNUpper
       
    ' Use the PrintOut method to print the remainder of the report by
    ' specifying 2 for the PageFrom argument and 32767 for the PageTo
    ' argument. Because 32767 is the maximum number of pages that can be
    ' printed, all remaining pages will be printed.
    DoCmd.PrintOut PrintRange:=acPages, PageFrom:=2, PageTo:=32767
    
    ' Close report without saving changes.
    DoCmd.Close ObjectType:=acReport, ObjectName:=strReportName,
Save:=acSaveNo

ChangeBins_End:
    Exit Sub
    
ChangeBins_Err:
    MsgBox Prompt:=Err.Description, Buttons:=vbCritical & vbOKOnly, _
        Title:="Error Number " & Err.Number & " Occurred"
    Resume ChangeBins_End
    
End Sub

Function GetPaperSize(frmName As Form) As AcPrintPaperSize
    
    ' Check the string in the cboPaperSize box, and
    ' pass back the corresponding AcPrintPaperSize
    ' constant.
    Select Case frmName!cboPaperSize
        Case "Letter"
            GetPaperSize = acPRPSLetter
        Case "Legal"
            GetPaperSize = acPRPSLegal
        Case "Statement"
            GetPaperSize = acPRPSStatement
        Case "Executive"
            GetPaperSize = acPRPSExecutive
    End Select
    
End Function

Function GetPaperBin(frmName As Form) As AcPrintPaperBin
    
    ' Check the string in the cboPaperBin box, and
    ' pass back the corresponding AcPrintPaperBin
    ' constant.
    Select Case frmName!cboPaperBin
        Case "Default"
            GetPaperBin = acPRBNAuto
        Case "Upper"
            GetPaperBin = acPRBNUpper
        Case "Middle"
            GetPaperBin = acPRBNMiddle
        Case "Lower"
            GetPaperBin = acPRBNLower
    End Select
    
End Function

Sub PrintReport(frmName As Form)
    Dim prtApp As Printer

    On Error GoTo PrintReport_Err
    
    ' Get selected printer and set user-specified settings
    Set prtApp = Application.Printers(frmName!cboPrinter.Value)
        
    With prtApp
        .PaperSize = modPrinters.GetPaperSize(frmName)
        .PaperBin = modPrinters.GetPaperBin(frmName)
        .Copies = frmName!txtCopies
        .Orientation = frmName!fraOrientation
    End With
    
    ' Set report's printer to selected printer.
    Reports(frmName!lstSelectReport).Printer = prtApp
    
    ' Check the value of the fraPrintRange option group
    ' frame to determine which option is selected. The
    ' OptionValue of the optAll option button is 1.
    If frmName!fraPrintRange = 1 Then
        DoCmd.PrintOut PrintRange:=acPrintAll
    Else
        DoCmd.PrintOut PrintRange:=acPages, PageFrom:=frmName!txtFrom, _
            PageTo:=frmName!txtTo
    End If

PrintReport_End:
    Exit Sub
    
PrintReport_Err:
    MsgBox Err.Description, vbCritical & vbOKOnly, _
        "Error Number " & Err.Number & " Occurred"
    Resume PrintReport_End
    
End Sub

Sub RestoreReportPrinter()
    Dim rpt As Report
    Dim prtOld As Printer
    Dim prtNew As Printer

    ' Open the Invoice report in Print Preview.
    DoCmd.OpenReport ReportName:="Invoice", View:=acViewPreview

    ' Initialize rpt variable.
    Set rpt = Reports!Invoice

    ' Save the report's current printer settings
    ' in the prtOld variable.
    Set prtOld = rpt.Printer

    ' Load the report's current printer settings
    ' into the prtNew variable.
    Set prtNew = rpt.Printer

    ' Change the report's Orientation property.
    prtNew.Orientation = acPRORLandscape

    ' Change other Printer properties, and then print
    ' or perform other operations here.

    ' If you comment out the following line of code,
    ' and a user interactively closes the report preview
    ' any changes made to properties of the report's Printer
    ' object are saved when the report is closed.
    Set rpt.Printer = prtOld

    ' Close report without saving.
    DoCmd.Close ObjectType:=acReport, ObjectName:="Invoice",
Save:=acSaveNo

End Sub

Sub GetPaperList()
' Uses DeviceCapabilities API function to display a message box
' with the name of the default printer and a list of
' the papers it supports.

    Dim lngPaperCount As Long
    Dim lngCounter As Long
    Dim hPrinter As Long
    Dim strDeviceName As String
    Dim strDevicePort As String
    Dim strPaperNamesList As String
    Dim strPaperName As String
    Dim intLength As Integer
    Dim strMsg As String
    Dim aintNumPaper() As Integer
    
    On Error GoTo GetPaperList_Err
    
    ' Get the name and port of the default printer.
    strDeviceName = Application.Printer.DeviceName
    strDevicePort = Application.Printer.Port
    
    ' Get the count of paper names supported by printer.
    lngPaperCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _
        lpPort:=strDevicePort, _
        iIndex:=DC_PAPERNAMES, _
        lpOutput:=ByVal vbNullString, _
        lpDevMode:=DEFAULT_VALUES)
    
    ' Re-dimension the array to the count of paper names.
    ReDim aintNumPaper(1 To lngPaperCount)
    
    ' Pad the variable to accept 64 bytes for each paper name.
    strPaperNamesList = String(64 * lngPaperCount, 0)

    ' Get the string buffer of all paper names supported by the printer.
    lngPaperCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _
        lpPort:=strDevicePort, _
        iIndex:=DC_PAPERNAMES, _
        lpOutput:=ByVal strPaperNamesList, _
        lpDevMode:=DEFAULT_VALUES)
    
    ' Get the array of all paper numbers supported by the printer.
    lngPaperCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _
        lpPort:=strDevicePort, _
        iIndex:=DC_PAPERS, _
        lpOutput:=aintNumPaper(1), _
        lpDevMode:=DEFAULT_VALUES)
    
    ' List the available paper names.
    strMsg = "Papers available for " & strDeviceName & vbCrLf
    For lngCounter = 1 To lngPaperCount
        
        ' Parse a paper name from the string buffer.
        strPaperName = Mid(String:=strPaperNamesList, _
            Start:=64 * (lngCounter - 1) + 1, Length:=64)
        intLength = VBA.InStr(Start:=1, String1:=strPaperName,
String2:=Chr(0)) - 1
        strPaperName = Left(String:=strPaperName, Length:=intLength)
        
        ' Add a paper number and name to text string for the message
box.
        strMsg = strMsg & vbCrLf & aintNumPaper(lngCounter) _
            & vbTab & strPaperName
            
    Next lngCounter
        
    ' Show the paper names in a message box.
    MsgBox Prompt:=strMsg

GetPaperList_End:
    Exit Sub
    
GetPaperList_Err:
    MsgBox Prompt:=Err.Description, Buttons:=vbCritical & vbOKOnly, _
        Title:="Error Number " & Err.Number & " Occurred"
    Resume GetPaperList_End
    
End Sub

Sub GetBinList(strName As String)
' Uses the DeviceCapabilities API function to display a
' message box with the name of the default printer and a
' list of the paper bins it supports.

    Dim lngBinCount As Long
    Dim lngCounter As Long
    Dim hPrinter As Long
    Dim strDeviceName As String
    Dim strDevicePort As String
    Dim strBinNamesList As String
    Dim strBinName As String
    Dim intLength As Integer
    Dim strMsg As String
    Dim aintNumBin() As Integer
    
    On Error GoTo GetBinList_Err
    
    ' Get name and port of the default printer.
    strDeviceName = Application.Printers(strName).DeviceName
    strDevicePort = Application.Printers(strName).Port
    
    ' Get count of paper bin names supported by printer.
    lngBinCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _
        lpPort:=strDevicePort, _
        iIndex:=DC_BINNAMES, _
        lpOutput:=ByVal vbNullString, _
        lpDevMode:=DEFAULT_VALUES)
    
    ' Re-dimension array to count of paper bins.
    ReDim aintNumBin(1 To lngBinCount)
    
    ' Pad variable to accept 24 bytes for each bin name.
    strBinNamesList = String(Number:=24 * lngBinCount, Character:=0)

    ' Get string buffer of paper bin names supported by printer.
    lngBinCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _
        lpPort:=strDevicePort, _
        iIndex:=DC_BINNAMES, _
        lpOutput:=ByVal strBinNamesList, _
        lpDevMode:=DEFAULT_VALUES)
        
    ' Get array of paper bin numbers supported by printer
    lngBinCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _
        lpPort:=strDevicePort, _
        iIndex:=DC_BINS, _
        lpOutput:=aintNumBin(1), _
        lpDevMode:=0)
        
    ' List available paper bin names.
    strMsg = "Paper bins available for " & strDeviceName & vbCrLf
    For lngCounter = 1 To lngBinCount
        
        ' Parse a paper bin name from string buffer.
        strBinName = Mid(String:=strBinNamesList, _
            Start:=24 * (lngCounter - 1) + 1, _
            Length:=24)
        intLength = VBA.InStr(Start:=1, _
            String1:=strBinName, String2:=Chr(0)) - 1
        strBinName = Left(String:=strBinName, _
                Length:=intLength)

        ' Add bin name and number to text string for message box.
        strMsg = strMsg & vbCrLf & aintNumBin(lngCounter) _
            & vbTab & strBinName
            
    Next lngCounter
        
    ' Show paper bin numbers and names in message box.
    MsgBox Prompt:=strMsg
    
GetBinList_End:
    Exit Sub
GetBinList_Err:
    MsgBox Prompt:=Err.Description, Buttons:=vbCritical & vbOKOnly, _
        Title:="Error Number " & Err.Number & " Occurred"
    Resume GetBinList_End
End Sub

Sub ClearReportSettings()
    Dim obj As AccessObject
    
    On Error GoTo ClearReportSettings_Err
    
    ' Open each report in the current project, and
    ' if the report is not using the default printer,
    ' reset its UseDefaultPrinter property to True.
    For Each obj In CurrentProject.AllReports
        DoCmd.OpenReport ReportName:=obj.Name, View:=acViewDesign
        If Not Reports(obj.Name).UseDefaultPrinter Then
            Reports(obj.Name).UseDefaultPrinter = True
            DoCmd.Save ObjectType:=acReport, ObjectName:=obj.Name
        End If
        DoCmd.Close
        DoEvents
    Next
    
    MsgBox Prompt:="Done!"

ClearReportSettings_End:
    Exit Sub
ClearReportSettings_Err:
    MsgBox Prompt:=Err.Description, Buttons:=vbCritical & vbOKOnly, _
        Title:="Error Number " & Err.Number & " Occurred"
    Resume ClearReportSettings_End
End Sub

>>>>>>>>> end msdn code


-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Gustav Brock
Sent: Wednesday, February 09, 2005 3:22 AM
To: accessd at databaseadvisors.com
Subject: RE: [AccessD] A97.
Reportwithprinterandpaperselectionpickswrongpaper when deployed on
identica


Hi Steve

Are the media/paper numbers real or hidden?
If I look up the data for PrintMediaReady it contains not a number but a
string with the actual name of the media, like Letter or A4.

/gustav

>>> Developer at UltraDNT.com 08-02-2005 18:13:13 >>>
Right.  Lets say invoice paper internally is 123 on your pc, but 149 on
the user's.  When you set yours, the application can't find the match at
the user, so the user's pc sets it to 1 (letter).  You can write the
correct value to registry, or, I imagine get the right number out of the
registry and just use that in the PRTDEVMODE API - but I havent used
that API in years, I don't remember all the intricacies of it (Its much
easier in Access XP+, with the Printer object). It could eventually fail
though, because the value only lasts until the user deletes the printer,
or deletes the custom paper.  If they do that, you have to dig around
for it again.

Steve


-----Original Message-----
From: accessd-bounces at databaseadvisors.com 
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Gustav Brock
Sent: Tuesday, February 08, 2005 11:40 AM
To: accessd at databaseadvisors.com 
Subject: RE: [AccessD] A97. Report with
printerandpaperselectionpickswrongpaper when deployed on identica


Hi Steve

That sounds close. 
So what you are saying is, that PrintMediaReady at the client initially
contains another media (paper format) than the one we wish to use? And
-
if once corrected, manually or by writing the registry - it will not
fail later?

/gustav


>>> Developer at UltraDNT.com 08-02-2005 17:15:38 >>>
The issue is in the way 2000/XP handles Custom paper.

In Me/98, you only had one custom paper size per machine, represented by
the constant 255.  In 2000/XP, there is support for multiple custom
paper sizes, therefore, it is some random number that Windows gives the
custom paper sizes, that can differ from PC to PC, even with apparently
identical setups. On your PC you are assigning a paper-size number that
the client doesn't have, as the default paper, when you set your paper
to Invoice.  The client PC defaults to letter because it can't find the
same paper size number as on your PC.

You have to dig in Registry, under:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Print\Printers\<<printer name>>\DsDriver
The PrintMediaSupported key has multiple values.  Find Invoice, then use
that as the value for PrintMediaReady.

Or - do what I did - give the user a "Setup" screen.

Steve

-- 
AccessD mailing list
AccessD at databaseadvisors.com
http://databaseadvisors.com/mailman/listinfo/accessd
Website: http://www.databaseadvisors.com




More information about the AccessD mailing list