MS Access Print Report с использованием VBA - PullRequest
1 голос
/ 18 апреля 2010

У меня очень интенсивный отчет по VBA. Когда я смотрю его, все замечательно, но когда я печатаю его после просмотра, все становится странно. Я потратил много часов на то, чтобы сузить возможности, и с определенной степенью уверенности пришел к выводу, что это ошибка в MS Access.

До этого момента мой метод печати отчетов состоял в том, чтобы открыть отчет с помощью docmd.openreport "report". Затем я использую команду docmd.printout, чтобы установить диапазон страниц, параметры сортировки и т. Д.

Есть ли способ напечатать отчет напрямую и при этом иметь возможность устанавливать такие параметры, как ярость страницы, сортировка и т. Д., Не выполняя предварительный просмотр?

Спасибо, Джефф

Ответы [ 3 ]

3 голосов
/ 19 апреля 2010

К сожалению, в коде нет способа сделать это полностью аккуратно, но все же это можно сделать после введения параметра WindowMode метода DoCmd.OpenReport. Это позволяет открыть отчет в режиме предварительного просмотра и скрыть его. Затем можно установить свойства объекта «Принтер» отчета (например, выходной принтер и ориентацию), а затем использовать 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

Форма диалога будет выглядеть примерно так:

альтернативный текст 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 для имени отчета, а затем делаю все на его основе, включая внесение изменений в свойства отчета на лету, что возможно потому, что отчет открыт в режиме предварительного просмотра, но не виден.

Например, у меня есть это событие AfterUpdate позади группы опций Layout:

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

Причина, по которой я меняю номера диапазонов страниц, заключается в том, что изменение ориентации, скорее всего, изменит количество страниц. В отличие от события OnOpen, изменения свойств формата отчета, открытого невидимым в режиме предварительного просмотра, происходят немедленно.

Я использую свои стандартные методы для диалоговых форм, то есть кнопки «Отмена» и «Продолжить» устанавливают для свойства формы .Visible значение False, что позволяет вызывающему коду продолжать работу. Для кнопки «Отмена» я установил для свойства .Tag формы значение «Отмена» и проверяю свойство .Tag, когда код продолжается в контексте вызова (см. Выше).

Итак, это не так здорово, как если бы можно было установить диапазон страниц непосредственно для объекта Printer, но он выполняет свою работу.

Одна вещь, которую необходимо изменить в рабочем коде, - убедиться, что в функции PrintReport был обработчик ошибок, чтобы в случае сбоя можно было снова включить Application.Echo (в противном случае пользователь может застрять в пустой экран и не может работать). Альтернативой было бы просто позволить отчету появляться на экране при вызове метода DoCmd.SelectObject. Но если я скрываю предварительный просмотр отчета от пользователя, я бы хотел пройти весь путь до конца.

Для получения дополнительной информации об этом вам следует исследовать объект .Printer в обозревателе объектов (F2 в VBE), а Статья базы знаний MS 290293 полезна для объяснения взаимодействия между Application.Printers. коллекция и объект Application.Printer и объекты, связанные с конкретным отчетом. Я также нашел небольшой учебник на сайте Office , который прояснил некоторые вещи.

1 голос
/ 18 апреля 2010

давно у меня был очень сложный случай. Мне нужно было создать несколько полей, переместить и отформатировать, и это можно было сделать только одним способом. я выбрал смелый подход, и это оказалось единственным способом: я открыл отчет скрытно и в режиме конструктора, велел vba все делать, и когда все было готово, отчет был изменен на обычный и видим для отображения и печати. ​​

0 голосов
/ 18 апреля 2010

Одним из решений является установка параметров принтера в дизайне отчета, сохранение этих изменений и печать их. Недостатком является то, что отчет будет привязан к определенному принтеру, если вы не зайдете в дизайн и не измените его.

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
...