【发布时间】:2014-10-06 22:02:23
【问题描述】:
目标:使用指定的 Win API 函数从字符串或富文本框打印到所需的任何打印机。
问题:在 VBA Access 中调用 StartDocPrinter 总是返回 0。
信息:下面的代码运行通过,没有中断。 OpenPrinter 似乎得到了很好的处理。调用StartDocPrinter时,返回0。
使用我尝试过的以下代码,
- 将不同的信息保存到
dDocInfo并根据@David_Heffernan 的建议,将 DOCINFO 属性声明为 Long 并将值设置为 0。- 当
.pDatatype = vbNullstring、GetLastError返回时,-
StartDocPrinter parameter Level=1时出现错误 124(无效级别) -
StarDocPrinter parameter Level=ByVal 1时出现错误 6(无效句柄),尽管 hPrinter 中显示了明显的有效句柄
-
- 当
.pDatatype = "RAW",GetLastError无论如何都会返回 0。 - 当
.pDatatype = 'vbNullString和任一 DOCINFO 属性设置为字符串时,GetLastError无论如何都会返回 0。
- 当
- 更改 WinAPI 函数的参数 (
ByRef DOCINFO) - 检查访问权限问题。从其他人的代码看来,将最后一个
OpenPrinter参数设置为0 应该将请求的打印机访问设置为PRINTER_ACCESS_USE。是否有可能 GetLastError 没有返回拒绝访问错误? - 将多个引用的代码从 C++ 转换为 VBA,但转换或不包括指针会令人困惑。我没有正确转换
StartDocPrinter(printer, 1, (LPBYTE) &docInfo);吗?
代码:
声明:
Type DOCINFO
pDocName As String
pOutputFile As String
pDatatype As String
End Type
Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, hPrinter As Long, ByVal pDefault As Long) As Long
Public Declare Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" (hPrinter As Long, Level As Long, dDocInfo As DOCINFO) As Long
功能:
Public Function printRawData(sPrinterName As String, lData As String) As Boolean
Dim bStatus As Boolean, hPrinter As Long, dDocInfo As DOCINFO, lJob As Long, nWritten As Integer
' Open a handle to the printer.
bStatus = OpenPrinter(sPrinterName, hPrinter, 0)
If bStatus Then
' Fill in the structure with info about this "document."
dDocInfo.pDocName = vbNullString
dDocInfo.pOutputFile = vbNullString
dDocInfo.pDatatype = "RAW"
' Inform the spooler the document is beginning.
lJob = StartDocPrinter(hPrinter, 1, dDocInfo) 'Returns 0 :(
Debug.Print hPrinter, sPrinterName, lJob, GetLastError()
If lJob > 0 Then
' Start a page.
bStatus = StartPagePrinter(hPrinter)
If bStatus Then
' Send the data to the printer.
bStatus = WritePrinter(hPrinter, lData, Len(lData), nWritten)
EndPagePrinter (hPrinter)
End If
' Inform the spooler that the document is ending.
EndDocPrinter (hPrinter)
End If
' Close the printer handle.
ClosePrinter (hPrinter)
End If
' Check to see if correct number of bytes were written.
If Not bStatus Or (nWritten <> Len(lData)) Then
printRawData = False
Else
printRawData = True
End If
End Function
参考资料/相关问题:
- http://support.microsoft.com/kb/154078 此代码的基本文件。 编辑:找到ByVal 在此处的一些声明中遗漏的位置。
- Send Raw Data to ZPL Printer using Visual Basic (MS Access 2000) 这个人似乎有效地使用了几乎相同的代码,那我为什么不能呢?这个问题的答案是用 C++ 编写的。
- http://www.cplusplus.com/forum/general/26184/这里的代码也是用C++写的,不知道怎么转换。
- http://codingdomain.com/visualbasic/win32api/datatypes/ 我在转换数据类型和指针时使用的指导,我不完全理解。
- StartDocPrinter(hPrinter, 1, di) returns false 这里提供了一些代码,但没有答案。这是我想到提供错误的地方。
- excel bva code to send command to usb printer 我试过了,但没有所需的访问权限。我仍然想知道如何正确使用上面的代码,即使我最终会这样做。
【问题讨论】:
-
可能代码中存在我们看不到的错误
-
添加了 DOCINFO 类型和到目前为止调用的函数的声明,
OpenPrinter和StartDocPrinter。 -
vbNullString不等于""。我认为你需要NULL。通过将记录的这些字段声明为Long并传递0,也许最简单。 -
我认为所有 DOCINFO 属性都可以是字符串?链接文档中的一些示例是
DOCINFO.DataType = "RAW"和DOCINFO.DocName = "AAAA"。字符串设置为 NULL 时会抛出错误。 -
@HansPassant 好的。我的代码复制和粘贴不够。我刚刚将 ByVal 添加到 hPrinter 和 Level 并且 lJob 返回 16。在 StartPagePrinter 上被轰炸,但可能出于类似的原因。