请问,怎样控制打印,以免打印队列内的打印任务越来越多导致系统的崩溃?

scyn 2004-09-21 11:06:35

我通过excel打印票据,将打印代码放在循环中

for i = 0 to PrintCnt - 1 Step 1

...

With objxlsWorksheets

.Cells(1, 2).Value = Data(i) '往excel里写数据
...

End With
...

objxlsWorksheets.PrintOut '通过excel打印

objxlsWb.Close False
bjxlsApp.Quit
Set objxlsWs = Nothing
Set objxlsWb = Nothing
Set objxlsApp = Nothing


...

Next

如果票据少的时候,打印一切正常,可是如果票据较多(循环次数较多),在打印到多半的时候,经常出现"内存不足"等错误提示,导致了系统崩溃甚至死机,剩下的票据无法正常打印。

请问,怎样实现在循环中控制一下,比如每打印10页后,让系统等待,等这10页打印结束后,再继续循环并打印。

急盼!! 谢谢!!

...全文
252 点赞 收藏 14
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
leolan 2004-09-27
你的是什麼操作系統?GetPrinter這個函數在不同OS下第2,3個參數是有區別的,看看MSDN.
回复
scyn 2004-09-27
请问,用lret = GetPrinter(hPrinter, 6, buffer, Len(buffer), SizeNeeded),获得打印机状态时
其返回值lret = 0(函数调用失败),而且buffer始终等于0,。buffer的值就是打印机的状态吗?

请高手再帮帮忙吧,我会马上结帖的!

谢谢,谢谢
回复
vzxq 2004-09-27
study
回复
scyn 2004-09-27
我用的是win2000专业版,我将第二个参数改成7,第三个参数改成b(0),返回值lret = 1,原来的
buffer还是不好用 :)

dim b(1000) as long

lret = GetPrinter(hPrinter, 7, b(0), 1000, SizeNeeded) '返回1

打印机在打印文档的时候,运行程序测试,lret = 1(函数调用成功),可是b(0)还是等于0,因为0是表示打印机空闲,没有打印文档,所以b(0)不应该等于0,应该是Print_Status_Busy = 215才对?
还是没有获得打印机状态。

小弟我太笨,找不出原因,请高手帮帮忙。

谢谢~~~~
回复
leolan 2004-09-25
Option Explicit

Private Enum Printer_Status
PRINTER_STATUS_READY = &H0
PRINTER_STATUS_PAUSED = &H1
PRINTER_STATUS_ERROR = &H2
PRINTER_STATUS_PENDING_DELETION = &H4
PRINTER_STATUS_PAPER_JAM = &H8
PRINTER_STATUS_PAPER_OUT = &H10
PRINTER_STATUS_MANUAL_FEED = &H20
PRINTER_STATUS_PAPER_PROBLEM = &H40
PRINTER_STATUS_OFFLINE = &H80
PRINTER_STATUS_IO_ACTIVE = &H100
PRINTER_STATUS_BUSY = &H200
PRINTER_STATUS_PRINTING = &H400
PRINTER_STATUS_OUTPUT_BIN_FULL = &H800
PRINTER_STATUS_NOT_AVAILABLE = &H1000
PRINTER_STATUS_WAITING = &H2000
PRINTER_STATUS_PROCESSING = &H4000
PRINTER_STATUS_INITIALIZING = &H8000
PRINTER_STATUS_WARMING_UP = &H10000
PRINTER_STATUS_TONER_LOW = &H20000
PRINTER_STATUS_NO_TONER = &H40000
PRINTER_STATUS_PAGE_PUNT = &H80000
PRINTER_STATUS_USER_INTERVENTION = &H100000
PRINTER_STATUS_OUT_OF_MEMORY = &H200000
PRINTER_STATUS_DOOR_OPEN = &H400000
PRINTER_STATUS_SERVER_UNKNOWN = &H800000
PRINTER_STATUS_POWER_SAVE = &H1000000
End Enum

Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long
Private Declare Function GetPrinter 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 ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

Private Sub Command1_Click()
MsgBox IsPrinterReady(Printer.DeviceName)
End Sub

Private Function IsPrinterReady(ByVal strDeviceName As String) As Boolean
Dim hPrinter As Long, lret As Long, SizeNeeded As Long, buffer As Long

lret = OpenPrinter(Printer.DeviceName, hPrinter, 0&)
lret = GetPrinter(hPrinter, 6, buffer, Len(buffer), SizeNeeded)
ClosePrinter hPrinter
IsPrinterReady = (buffer = Printer_Status.PRINTER_STATUS_READY)

End Function
回复
scyn 2004-09-25
通过EnumJobs获取打印的JobCount,也就是返回打印队列中的打印任务数量。我使用本地打印机测试打印的时候,程序一切正常。但实际使用的是一台网络打印机(EPSON AL-C4000),打印机本身有内存,打印的时候在Windows下的打印队列窗口里根本没有显示出打印任务(队列),所以程序判断打印任务总是0,EnumJobs函数就不好用了 -_-、

请问高手们,还有其他方法能判断打印机当前的状态吗?比如不判断打印任务数量,而判断当前打印是否结束等等,如果结束再向打印机发送打印任务。

小弟跪谢~~~~~~!!!!! 急盼!! 谢谢!
回复
scyn 2004-09-22
谢谢 ! 这个方法:do while GetJobCount = 0 我刚试过,好用:)

是不是在do while 循环的时候,外面的for .. next循环就"暂停"了,等到do循环完毕(也就是当前10个打印任务结束了),for循环还可以继续,就相当于系统在等待了?
谢谢!
回复
leolan 2004-09-22
For i = .................

if count = 10 then

do while GetJobCount = 0 //不停地獲取打印機任務數量
count = 0
loop

end if

//打印

count = count + 1

Next
回复
scyn 2004-09-22
请问,如果是这样实现:
在循环中加一个用于累计的变量(count = count + 1),当累计到10的时候(也就是PrintOut了10次的时候)就去判断打印队列中是否有打印任务(通过EnumJobs获取打印的JobCount.),如果还有打印任务,则系统等待,循环暂停,如果没有打印任务,则循环继续并打印,累计变量清零。

请问,系统等待的部分应该怎样实现呢? 怎样实现暂停循环,等打印结束时再继续?
(在循环暂停的时候怎样判断?)

For i = .............
....

count = count + 1

if count = 10 then
'判断是否有打印任务(通过api)
...
if 有任务 then
'怎样实现暂停循环(系统等待)
'怎样判断打印已经结束了,可以继续循环了?

else
count = 0
end if

end if

Next

谢谢!! 谢谢! 急盼~!

回复
101monster 2004-09-21
呵呵,UP!
回复
jam021 2004-09-21
想得到各打印作业的状态,通常我们可以通过调用以下API:
   OpenPrinter
   GetPrinter
   EnumJobs
   ClosePrinter
目前在微软的网站上没有现成的关于以上API调用的VB代码,但有一篇VC的示例代码,您可以参考一下:

   HOWTO: Get the Status of a Printer and a Print Job
   (http://support.microsoft.com/support/kb/articles/Q160/1/29.asp)
回复
RUKYO 2004-09-21
找了个控制打印机状态的API
【VB声明】
Private Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Byte, ByVal Command As Long) As Long

【别名】
SetPrinterA

【说明】
对一台打印机的状态进行控制

【返回值】
Long,非零表示成功,零表示失败。会设置GetLastError

【备注】
在PRINTER_INFO_2结构的基础上设置打印机状态时,pServerName,AveragePPM,Status和cJobs字段都会被忽略

【参数表】
hPrinter ------- Long,指定一个已打开的打印机的句柄(用OpenPrinter取得)

Level ---------- Long,0,2或3(4或5用于windows95,5或6用于NT 4.0)。如Command不是零,则这个参数必须是零

pPrinter ------- Byte,包含一个PRINTER_INFO_x的结构的缓冲区,其中的x代表级别的设定(Level)。假如级别为零,并且Command设为PRINTER_CONTROL_SET_STATUS,那缓冲区就包含了一个PRINTER_CONTROL_STATUS结构。否则,如级别为零,就设为NULL(要把声明变成ByVal
As Long,以便传递零值)

Command -------- Long,下述值之一:                   

根据PRINTER_INFO_x结构改变打印机
PRINTER_CONTROL_PAUSE
暂停打印机
PRINTER_CONTROL_PURGE
删除打印机的所有作业
PRINTER_CONTROL_RESUME
恢复一台暂停的打印机
PRINTER_CONTROL_SET_STATUS
载入打印机的PRINTER_CONTROL_STATUS结构(不可在NT 3.51下使用)
回复
RUKYO 2004-09-21
http://www.yesky.com/20020128/215704.shtml
回复
leolan 2004-09-21
//可用EnumJobs獲取打印的JobCount.

Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As Any) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Function EnumJobs Lib "winspool.drv" Alias "EnumJobsA" (ByVal hPrinter As Long, ByVal FirstJob As Long, ByVal NoJobs As Long, ByVal Level As Long, pJob As Any, ByVal cdBuf As Long, pcbNeeded As Long, pcReturned As Long) As Long
Private Sub Form_Load()
Dim hPrinter As Long, lNeeded As Long, lReturned As Long
Dim lJobCount As Long
OpenPrinter Printer.DeviceName, hPrinter, ByVal 0&
EnumJobs hPrinter, 0, 99, 1, ByVal 0&, 0, lNeeded, lReturned
If lNeeded > 0 Then
ReDim byteJobsBuffer(lNeeded - 1) As Byte
EnumJobs hPrinter, 0, 99, 1, byteJobsBuffer(0), lNeeded, lNeeded, lReturned
If lReturned > 0 Then
lJobCount = lReturned
Else
lJobCount = 0
End If
Else
lJobCount = 0
End If
ClosePrinter hPrinter
MsgBox "Jobs in printer queue: " + CStr(lJobCount), vbInformation
End Sub
回复
相关推荐
发帖

1187

社区成员

VB 数据库(包含打印,安装,报表)
申请成为版主
帖子事件
创建了帖子
2004-09-21 11:06
社区公告
暂无公告