2

我正在尝试使用一些 Word 2007 自动化,我们让用户能够选择要打印的打印机并编译 Word 文档。我们提供在本地或网络打印机上打印的能力。网络打印机在代码中由它们的完全限定路径(打印机名 + 端口,如果有的话)指定。

问题是在 Windows 2008 终端服务器中,当默认为网络打印机时,更改打印机不起作用。当原始默认设置为本地打印机时,它可以正常工作。

我们通过以下方式打印文档:

  1. 将默认打印机更改为用户想要的打印机。(由Application.ActivePrinter完成)
  2. 打印文档。
  3. 将默认打印机改回原来的默认值。

当我在 Word 2007 中将默认打印机设置为网络打印机(重定向打印机)时,它不会更改打印机,但是在 Word 2003 中它确实可以工作,但在我的情况下这不是一个选项。我必须让它与 Word 2007 一起工作。

有更好的解决方案还是我做错了什么?

示例代码如下,我尝试通过在 ActivePrinter 和 strPrinterName 更改上使用断点来调试它。

示例代码的参考:

http://www.erlandsendata.no/english/index.php?d=envbaprintchangeprinter

http://www.ozgrid.com/forum/showthread.php?t=68990

示例代码:

Option Explicit

Const PRINTER_ENUM_CONNECTIONS = &H4
Const PRINTER_ENUM_LOCAL = &H2

Private Declare Function EnumPrinters Lib "winspool.drv" Alias "EnumPrintersA" _
        (ByVal flags As Long, ByVal name As String, ByVal Level As Long, _
        pPrinterEnum As Long, ByVal cdBuf As Long, pcbNeeded As Long, _
        pcReturned As Long) As Long

Private Declare Function PtrToStr Lib "kernel32" Alias "lstrcpyA" _
        (ByVal RetVal As String, ByVal Ptr As Long) As Long

Private Declare Function StrLen Lib "kernel32" Alias "lstrlenA" _
       (ByVal Ptr As Long) As Long


Public Function ListPrinters() As Variant

Dim bSuccess As Boolean
Dim iBufferRequired As Long
Dim iBufferSize As Long
Dim iBuffer() As Long
Dim iEntries As Long
Dim iIndex As Long
Dim strPrinterName As String
Dim iDummy As Long
Dim iDriverBuffer() As Long
Dim StrPrinters() As String

iBufferSize = 3072

ReDim iBuffer((iBufferSize \ 4) - 1) As Long

'EnumPrinters will return a value False if the buffer is not big enough
bSuccess = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
        PRINTER_ENUM_LOCAL, vbNullString, _
        1, iBuffer(0), iBufferSize, iBufferRequired, iEntries)

If Not bSuccess Then
    If iBufferRequired > iBufferSize Then
        iBufferSize = iBufferRequired
        Debug.Print "iBuffer too small. Trying again with "; _
        iBufferSize & " bytes."
        ReDim iBuffer(iBufferSize \ 4) As Long
    End If
    'Try again with new buffer
    bSuccess = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
            PRINTER_ENUM_LOCAL, vbNullString, _
            1, iBuffer(0), iBufferSize, iBufferRequired, iEntries)
End If

If Not bSuccess Then
    'Enumprinters returned False
    MsgBox "Error enumerating printers."
    Exit Function
Else
    'Enumprinters returned True, use found printers to fill the array
    ReDim StrPrinters(iEntries - 1)
    For iIndex = 0 To iEntries - 1
        'Get the printername
        strPrinterName = Space$(StrLen(iBuffer(iIndex * 4 + 2)))
        iDummy = PtrToStr(strPrinterName, iBuffer(iIndex * 4 + 2))
        StrPrinters(iIndex) = strPrinterName
    Next iIndex
End If

ListPrinters = StrPrinters

End Function


'You could call the function as follows:




Sub Test()

Dim StrPrinters As Variant, x As Long
Dim strPrinterName As String

StrPrinters = ListPrinters

'Fist check whether the array is filled with anything, by calling another function, IsBounded.
If IsBounded(StrPrinters) Then
    For x = LBound(StrPrinters) To UBound(StrPrinters)
        Debug.Print StrPrinters(x)

     ' Message out Printer name
        strPrinterName = StrPrinters(x)

      ' Message otu Active Printer
        Application.ActivePrinter = GetFullNetworkPrinterName(strPrinterName)


    Next x
Else
    Debug.Print "No printers found"
End If

End Sub




Public Function IsBounded(vArray As Variant) As Boolean

    'If the variant passed to this function is an array, the function will return True;
    'otherwise it will return False
    On Error Resume Next
    IsBounded = IsNumeric(UBound(vArray))

End Function


Function GetFullNetworkPrinterName(strNetworkPrinterName As String) As String
' returns the full network printer name
' returns an empty string if the printer is not found
' e.g. GetFullNetworkPrinterName("HP LaserJet 8100 Series PCL")
' might return "HP LaserJet 8100 Series PCL on Ne04:"
Dim strCurrentPrinterName As String, strTempPrinterName As String, i As Long
    strCurrentPrinterName = Application.ActivePrinter
    i = 0
    Do While i < 100
        strTempPrinterName = strNetworkPrinterName & " on Ne" & Format(i, "00") & ":"
        On Error Resume Next ' try to change to the network printer
        Application.ActivePrinter = strTempPrinterName
        On Error GoTo 0
        If Application.ActivePrinter = strTempPrinterName Then
            ' the network printer was found
            GetFullNetworkPrinterName = strTempPrinterName
            i = 100 ' makes the loop end
        End If
        i = i + 1
    Loop
    ' remove the line below if you want the function to change the active printer
    'Application.ActivePrinter = strCurrentPrinterName ' change back to the original printer
End Function
4

2 回答 2

1

会不会是安全?用户是否正确设置了访问网络打印机的安全权限?

于 2010-02-25T21:28:22.710 回答
0

我们最终在 Word 之外解决了这个问题。我们现在直接使用 Win32 API,然后只调用 word 进行打印。

于 2010-02-26T19:42:42.257 回答