Основная задача кодов Visual Basic for Applications - автоматизация. И задачи зачастую бывают самые разные. Одна из таких задач - печать листов или ячеек по условию или в цикле. Сама по себе отправка на печать листа или диапазона не представляет сложностей, это легко можно записать макрорекордером и вставить в свой код. Выглядеть это будет примерно так:
Sub Макрос1() ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True, IgnorePrintAreas:=False End Sub |
Но зачастую необходимо не просто отправить на печать, а еще и на определенный принтер. При этом не просто указать другой принтер, а дать возможность выбрать принтер пользователю, не задавая его жестко в коде. Ведь у разных пользователей могут быть разные принтеры подключены. Часто такое необходимо при печати этикеток или других специфических материалов(открытки, буклеты и т.п.) потому, что для них как правило используют не стандартный офисный черно-белый лазерный принтер, а некий более продвинутый с возможностью заправки специфических листов. Как видно из кода выше - там нет и малейшего намека на указание принтера. Хотя в принципе параметр такой есть - ActivePrinter.
На самом деле есть несколько вариантов выбора принтера, но я покажу самый надежный (как оказалось) и в тоже время самый простой - через стандартный диалог выбора принтеров:
Sub ShowPrinters() Application.Dialogs(xlDialogPrinterSetup).Show End Sub |
Этот диалог после вызова автоматически назначает выбранный в нем принтер принтером по умолчанию для печати. Т.е. теперь чтобы мы ни отправили на печать будет отправлено на этот принтер. Все бы хорошо, но тут появляется небольшая проблема: в этом случае у нас не только из кодов будет идти печать на этот принтер, но и при обычной печати. А это нам не надо, ведь тогда даже 100500 каких-то "левых" документов вместо печати на лазерном черно-белом будут распечатаны на офигительном цветном. За такое можно и премии лишиться :) Конечно, можно каждый раз перед ручной печатью выставлять нужный принтер. Но во-первых об этом можно просто забыть, а во-вторых - как только изменим один раз, нам придется перед печатью из кода опять менять принтер. Замкнутый круг и автоматизацией вообще не пахнет.
Поэтому лучше чуть-чуть все усложнить и при каждой печати из кода VBA назначать нужный принтер. Я заготовил универсальный код, который отправляет на печать либо активный лист, либо указанный диапазон ячеек именно на выбранный для печати из VBA принтер. При желании и умении код можно доработать для печати листов и диапазонов в цикле. Но основной упор сделан на выбор принтера для печати только из кода. Т.е. при первом запуске кода печати будет предложено выбрать принтер:
Если принтер будет выбран и нажата кнопка Ок, то принтер будет запомнен и сразу после этого сброшен и установлен заново тот принтер, который был изначально установлен для печати. Однако при печати из кода будет использован именно выбранный принтер, а не тот, который будет применяться при ручной печати.
Т.е. при ручной печати будет один принтер, а при печати из кода - другой.
Option Explicit 'глобальная переменная для хранения значения выбранного принтера при печати из VBA Public sNowPrinter As String '--------------------------------------------------------------------------------------- ' Procedure : ChangePrinter ' Author : The_Prist(Щербаков Дмитрий) ' Purpose : Функция выбора принтера для печати из кода VBA '--------------------------------------------------------------------------------------- Sub ChangePrinter() sNowPrinter = "Set" Dim v, s 'запоминаем текущий принтер, чтобы можно было вернуть его после выбора s = Application.ActivePrinter 'показываем окно выбора принтера v = Application.Dialogs(xlDialogPrinterSetup).Show 'если принтер был выбран - запоминаем выбор If v = True Then sNowPrinter = Application.ActivePrinter End If 'возвращаем принтер по умолчанию, чтобы стандартная печать шла на него Application.ActivePrinter = s End Sub '--------------------------------------------------------------------------------------- ' Procedure : DoPrint ' Author : The_Prist(Щербаков Дмитрий) ' Purpose : Функция печати указанного кол-ва копий указанного диапазона ячеек ' rr - ссылка на диапазон ячеек - Range("A1:B10") ' если не указан - на печать выводится весь активный лист ' lCopies - целое число, указывающее сколько копий выводить на печать ' если не указан - на печать выводится одна копия '--------------------------------------------------------------------------------------- Function DoPrint(Optional rr As Range = Nothing, Optional lCopies As Long = 1) Dim sActPrinter As String 'проверяем, установлен ли ранее принтер для печати If sNowPrinter = "" Or sNowPrinter = "Set" Then 'если нет - вызываем процедуру выбора принтера Call ChangePrinter 'если выбранный принтер не был выбран(нажали Отмена), то используем текущий If sNowPrinter = "Set" Then If MsgBox("Не выбран принтер для печати. Использовать установленный в качестве активного?", vbCritical + vbYesNo, "www.excel-vba.ru") = vbNo Then Exit Function End If sActPrinter = Application.ActivePrinter Else sActPrinter = sNowPrinter 'получаем выбранный в окне принтер End If End If If rr Is Nothing Then 'печатаем активный лист на выбранном принтере ActiveSheet.PrintOut Copies:=lCopies, ActivePrinter:=sActPrinter Else 'печатаем указанный диапазон ячеек на выбранном принтере rr.PrintOut Copies:=lCopies, ActivePrinter:=sActPrinter End If End Function |
Функция
Функция
При этом функция
В процедуре ниже на печать выводится выделенный диапазон с количеством печатных копий листов - 2.
Sub TestPrint() DoPrint Selection, 2 End Sub |
Так же в функции
В приложенном к статье файле так же есть пример печати по очереди каждой из этикеток, расположенных в два ряда:
Хотя практичнее автоматически заполнять только один шаблон этикетки в цикле разными данными и его отправлять на печать.
Выбор принтера (74,5 КиБ, 1 699 скачиваний)
Здравствуйте! Столкнулся с проблемой, после установки любого принтера в системе пользователя один из файлов Excel при запуске начинает обращаться к подсистеме печати, и показывает окно выбора принтеров, точно такое же как у Вас в статье, далее все запускается в штатном режиме, но не надолго, при попытке выделить ячейки и скопировать их появляется сообщение о том, что печать невозможна так как буфер переполнен, при том что я не пытаюсь печатать, а всего лишь пытаюсь скопировать ячейки, это делает работу с файлом просто навсего невозможной. Запуск на другой машине привел к тому же самому, и на той и на другой установлен Office 2010, могу сделать вывод что дело в файле, но куда копать не знаю, он очень объемный и обладает кучей формул, но без макросов и как я понял без VBA скриптов. Просмотрел данный файл в редакторе VBA ничего не нашел, как избавиться от этой проблемы?
Антон, в данной ситуации могу посоветовать лишь одно: отключить принтер от ПК, сбросить полностью параметры печати в этой книге, а так же удалить все представления(Вид -Представления).
Если книга в общем доступе - сначала снять общий доступ, удалив журнал и представления.
Доброго времени суток. Функция ChangePrinter работает отлично, спасибо Вам, Ваши статьи очень информативны. Однако у меня проблема вот в чем. Функция выбора принтера мне нужна не для выбора принтера по принципу хочу \не хочу, а по принципу, работает\не работает. Поэтому, Ваша форма позволяет мне выбрать принтер, но сначала я должен определить какой из принтеров сейчас в сети, а это для обычного юзера может стать неразрешимой задачей) Есть ли возможность добавить в форму статус принтера? Или это "много кода"))? В любом случае, Спасибо.
Здравствуйте!
Есть ли возможность создать TextBox в UserForm, и в зависимости от числа в TextBox (1, 2, 3...), выводить на печать соответствующее число копий?