2010-04-18 197 views
1

我有一個非常強大的VBA報告。當我預覽它時,一切都很棒,但是當我預覽完東西后打印出來的時候會變得古怪。我花了很多時間縮小了可能性,並且以一定的信心得出結論,這是MS Access中的一個錯誤。使用VBA的MS Access打印報告

到目前爲止,我打印報告的方法是使用docmd.openreport "report"打開報告。然後我使用docmd.printout命令,以便我可以設置頁面範圍,排序規則等。

有沒有辦法直接打印報告,並且仍然可以設置諸如頁面風格,整理等選項,而無需首先進行預覽?

感謝, 傑夫

回答

1

不久前,我有一個非常困難的情況下。我不得不做一些現場創作,移動和格式化,這隻能以一種方式完成。我採取了一種大膽的方式,它變成了唯一的方法:我在設計模式下隱藏了報告,讓vba做到了這一點,完成後,報告變爲正常顯示和打印。

+0

唉。這聽起來很醜陋。另一方面,它適合於正常的Access範例! – MJB 2010-04-18 14:59:38

+0

BZZZZT !!!!它絕對不適合任何訪問範例。直到Access 2002推出一個適當的打印機對象才能完全控制打印。這是因爲VB和Windows打印系統存在遺留問題。引進MDE之前,它是不是這樣的一個問題,因爲你可以使在設計視圖中的變化,但隨着越來越多地使用MDES的(背後的幕後首先介紹了A95,並首次引入到最終用戶的A97 ),它成了一個真正的問題。爲什麼花了他們這麼長的時間才解決它,我不能說。 – 2010-04-18 22:50:05

+0

相信與否,這實際上解決了我的問題。我知道這是很醜陋的,不得不在設計模式下打開它,但是,如果它有效,你能說什麼? – Icode4food 2010-04-19 12:36:13

0

一種解決方案是在報告設計中設置打印機選項,保存這些更改並打印出來。缺點是,除非您進入設計並進行更改,否則這會將報告與特定的打印機相關聯。

DoCmd.OpenReport "ReportName", acViewDesign, Null, Null, acHidden 

Dim oRpt As Report 
Set oRpt = Reports(0) 
oRpt.UseDefaultPrinter = False 
oRpt.Printer = Application.Printers("printer name") 

With oRpt.Printer 
    .PaperBin = acPRBNAuto 
    .PaperSize = acPRPSLetter 
    .Copies = 1 
    .PrintQuality = acPRPQMedium 
End With 

DoCmd.Close acReport, "ReportName", acSaveYes 
DoCmd.OpenReport "ReportName", acViewNormal 

Set oRpt = Nothing 
3

不幸的是沒有辦法在代碼中做到這一點完全整齊,但它仍然出臺以來DoCmd.OpenReport方法的WindowMode參數來完成。這樣就可以在打印預覽模式下打開報告並將其隱藏起來。然後,您可以設置報表的打印機對象的屬性(如輸出打印機和方向),然後使用DoCmd.PrintOut打印頁面範圍。

有一點需要注意:

你不能在報表的OnOpen事件做到這一點,因爲改變任何對佈局產生影響,不會給你正確的結果。例如,如果在OnOpen事件中,您已從縱向更改爲橫向,您將無法準確計數報告中有多少頁面,因爲報告在OnOpen事件觸發時未被格式化。儘管對於除頁面以外的所有內容都沒有問題。

我要實現這個的方式是使用公共函數和對話框。該功能會是這個樣子:

Public Function PrintReport(strReport As String) As Boolean 
    ' open report in PREVIEW mode but HIDDEN 
    DoCmd.OpenReport strReport, acViewPreview, , , acHidden 
    ' open the dialog form to let the user choose printing options 
    DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport 
    With Forms!dlgPrinter 
     If .Tag <> "Cancel" Then 
     Set Reports(strReport).Printer = Application.Printers((!cmbPrinter)) 
     Reports(strReport).Printer.Orientation = !optLayout 
     Application.Echo False 
     DoCmd.SelectObject acReport, strReport 
     DoCmd.PrintOut acPages, !txtPageFrom, !txtPageTo 
     PrintReport = True 
     End If 
    End With 
    DoCmd.Close acForm, "dlgPrinter" 
    DoCmd.Close acReport, strReport 
    Application.Echo True 
    End Function 

對話框的形式會是這個樣子:

alt text http://dfenton.com/DFA/examples/PrinterProperties.png

正如你可以在上面看到,我打開此對話框與OpenArg參數,這是報告的名稱。在對話框的onload事件,我初始化窗體上的控件:

Dim varPrinter As Printer 
    Dim strRowsource As String 
    Dim strReport As String 

    If Len(Me.OpenArgs) > 0 Then 
    strReport = Me.OpenArgs 
    Me.Tag = strReport 
    For Each varPrinter In Application.Printers 
     strRowsource = strRowsource & "; " & varPrinter.DeviceName 
    Next varPrinter 
    Me!cmbPrinter.RowSource = Mid(strRowsource, 3) 
    ' first check to see that the report is still open 
    If (1 = SysCmd(acSysCmdGetObjectState, acReport, strReport)) Then 
     With Reports(strReport).Printer 
      Me!cmbPrinter = .DeviceName 
      Me!optLayout = .Orientation 
     End With 
     Me!txtPageTo = Reports(strReport).Pages 
    End If 
    End If 

我使用窗體的.TAG財產報告名稱,然後以此爲基礎進行的一切,包括進行更改的飛行報告屬性,這是可能的,因爲報告以預覽模式打開,但不可見。

舉例來說,我有佈局選項組這背後更新後事件:

With Reports(Me.Tag) 
    .Printer.Orientation = Me!optLayout 
    Me!txtPageTo = .Pages 
    End With 

我改變頁面範圍內的數字的原因是因爲改變方向將最有可能改變的頁數。與OnOpen事件不同,在打印預覽模式下無形打開的報告的格式屬性更改會立即發生。

我用我的標準方法對話框的形式,這是有設置窗體的。可見屬性設爲False,它允許調用代碼繼續取消並繼續按鈕。對於「取消」按鈕,我將表單的.Tag屬性設置爲「取消」,並在代碼在調用上下文中繼續時檢查.Tag屬性(請參見上文)。

那麼,這是不是一樣大,這將是能夠直接將打印機對象的頁面範圍,但它能夠完成任務。

生產代碼中需要更改的一件事是確保PrintReport函數中有一個錯誤處理程序,以便如果出現錯誤,可以重新啓用Application.Echo(否則,用戶可能會卡住與一個空白的屏幕,無法工作)。另一種方法是在調用DoCmd.SelectObject方法時讓報告出現在屏幕上。但是,如果我隱藏用戶的報告預覽,我會想要一路走下去。

欲瞭解更多信息,您應該在對象瀏覽器(VBE中的F2)中調查.Printer對象,並且MS Knowledge Base article 290293有助於解釋Application.Printers集合和Application.Printer對象之間的交互以及與特定報告相關聯。我還發現a little tutorial on the Office site澄清了一些事情。

+0

這個答案是UNNECESSARILY COMPLEX。我能夠使用Access'在我張貼在我的問題結束,在這個環節的答案內置方法做同樣的事情在更少的代碼:http://stackoverflow.com/questions/19802553/runtime-error -2448-你-着指派-a值到這個對象 – CodeMed 2013-11-06 18:14:47