Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/47: Рейтинг темы: голосов - 47, средняя оценка - 4.62
1712 / 579 / 76
Регистрация: 10.04.2009
Сообщений: 9,327

Выяснить сколько доступных для печати принтеров и их марку

14.09.2012, 16:54. Показов 9666. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, как этот список на страницу Ворда вынести? Спасибо
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.09.2012, 16:54
Ответы с готовыми решениями:

Список доступных принтеров
Доброе время суток! Прошу сильно не пинать......в основном то я по Delphi, но нужда заставила по VBA. В общем в екселе есть...

Получить список доступных принтеров
Печатаю форму методом UserForm.PrintForm Подскажите, пожалуйста, как: 1. Получить список доступных принтеров (хочу сделать выборку на...

Правильная настройка устаревших принтеров для печати из Windows Server 2008 terminal Server
Уважаемые админы - тема весьма щепетильна, но спасительного решения так до сих пор и не найдено (на данном форуме тоже), опробованы многие...

19
 Аватар для Апострофф
9908 / 3924 / 742
Регистрация: 11.10.2011
Сообщений: 5,904
14.09.2012, 22:06
Список доступных принтеров
0
1712 / 579 / 76
Регистрация: 10.04.2009
Сообщений: 9,327
14.09.2012, 23:23  [ТС]
спасибо, смотрю, порылся у себя в записях, нашёл

ActivePrinter = "\\NAME\Printer"
Имя принтера нужно указывать вместе с путём и с точностью до символа. В результате выполнения этой команды принтер по умолчанию будет переназначен

Что написал сам не знаю, никто не знает, что имелось ввиду?

Добавлено через 11 минут
ну нет, у меня формы пока так пробую
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Const PRINTER_ENUM_CONNECTIONS = &H4
Const PRINTER_ENUM_LOCAL = &H2
 
Private Declare Function EnumPrinters Lib "winspool.drv" Alias "EnumPrintersA" _
        (ByVal flags As Long, ByVal name As String, ByVal Level As Long, _
        pPrinterEnum As Long, ByVal cdBuf As Long, pcbNeeded As Long, _
        pcReturned As Long) As Long
 
Private Declare Function PtrToStr Lib "kernel32" Alias "lstrcpyA" _
        (ByVal RetVal As String, ByVal Ptr As Long) As Long
 
Private Declare Function StrLen Lib "kernel32" Alias "lstrlenA" _
       (ByVal Ptr As Long) As Long
  
Public Function ListPrinters() As Variant
 
Dim bSuccess As Boolean
Dim iBufferRequired As Long
Dim iBufferSize As Long
Dim iBuffer() As Long
Dim iEntries As Long
Dim iIndex As Long
Dim strPrinterName As String
Dim iDummy As Long
Dim iDriverBuffer() As Long
Dim strPrinters() As String
 
iBufferSize = 3072
 
ReDim iBuffer((iBufferSize \ 4) - 1) As Long
 
'EnumPrinters will return a value False if the buffer is not big enough
bSuccess = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
        PRINTER_ENUM_LOCAL, vbNullString, _
        1, iBuffer(0), iBufferSize, iBufferRequired, iEntries)
 
If Not bSuccess Then
    If iBufferRequired > iBufferSize Then
        iBufferSize = iBufferRequired
        Debug.Print "iBuffer too small. Trying again with "; _
        iBufferSize & " bytes."
        ReDim iBuffer(iBufferSize \ 4) As Long
    End If
    'Try again with new buffer
    bSuccess = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
            PRINTER_ENUM_LOCAL, vbNullString, _
            1, iBuffer(0), iBufferSize, iBufferRequired, iEntries)
End If
 
If Not bSuccess Then
    'Enumprinters returned False
    MsgBox$ "Error enumerating printers."
    Exit Function
Else
    'Enumprinters returned True, use found printers to fill the array
    ReDim strPrinters(iEntries - 1)
    For iIndex = 0 To iEntries - 1
        'Get the printername
        strPrinterName = Space$(StrLen(iBuffer(iIndex * 4 + 2)))
        iDummy = PtrToStr(strPrinterName, iBuffer(iIndex * 4 + 2))
        strPrinters(iIndex) = strPrinterName
        'Debug.Print strPrinterName
    Next iIndex
End If
 
ListPrinters = strPrinters
MsgBox$ ListPrinters
 
End Function
 
Private Sub UserForm_Activate()
 
    Selection.TypeText Text:=ListPrinters
    
End Sub
спотыкаюсь на 68 строке
ошибка 13 Tipe mismatch
??
0
 Аватар для Апострофф
9908 / 3924 / 742
Регистрация: 11.10.2011
Сообщений: 5,904
15.09.2012, 07:26
Лучший ответ Сообщение было отмечено как решение

Решение

Ципихович Эндрю, пора бы узнать, как выводятся массивы!
Visual Basic
1
MsgBox$ join(ListPrinters, vbcrlf)
3
1712 / 579 / 76
Регистрация: 10.04.2009
Сообщений: 9,327
15.09.2012, 09:18  [ТС]
Цитата Сообщение от Апострофф Посмотреть сообщение
пора бы узнать, как выводятся массивы!
не спорю, а если ситуация знал и забыл, спасибо
но тут ещё надо оставить в списке только те, которые "Готов" в панели управления, можно? как?
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
17.09.2012, 00:38
Лучший ответ Сообщение было отмечено как решение

Решение

Ципихович Эндрю, Вы хотели спросить - включен или нет?
(в Win7 и др. версиях терминология немного отличается (у меня пишет "Свободен", при чем даже когда отключен. Этот статус напрямую связан с состоянием печати).

Вот описание WMI-класса на MSDN http://msdn.microsoft.com/en-u... s.85).aspx
(как то через API мне это написать сложновато).
Подлатал. Итого:
1) Коротко самые основные параметры:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Option Explicit
'Win32_Printer class - [url]http://msdn.microsoft.com/en-us/library/windows/desktop/aa394363(v=vs.85).aspx[/url]
 
Sub PrinterList()
Dim oPRN As Object
Dim PrnStatusEn$(1 To 7)
Dim PrnStatusRu$(1 To 7)
 
PrnStatusEn(1) = "Other"
PrnStatusEn(2) = "Unknown"
PrnStatusEn(3) = "Idle"
PrnStatusEn(4) = "Printing"
PrnStatusEn(5) = "Warming Up"
PrnStatusEn(6) = "Stopped printing"
PrnStatusEn(7) = "Offline"
 
PrnStatusRu(1) = "Другой"
PrnStatusRu(2) = "Неизвестно"
PrnStatusRu(3) = "Свободен"
PrnStatusRu(4) = "Печать"
PrnStatusRu(5) = "Разогрев"
PrnStatusRu(6) = "Завершение печати"
PrnStatusRu(7) = "Вне сети"
 
For Each oPRN In GetObject("WinMgmts:{ImpersonationLevel=Impersonate}!//./root/CIMV2").ExecQuery _
        ("SELECT * FROM Win32_Printer")
  If oPRN.workoffline = False Then 'Готов ли к работе
    If InStr(oPRN.PortName, "USB") <> 0 Then 'Железный ли принтер (не-виртуальный)
      Debug.Print "Имя: "; oPRN.Name
      Debug.Print "Порт: "; oPRN.PortName
      Debug.Print "Статус: "; PrnStatusEn(oPRN.PrinterStatus) & " " & PrnStatusRu(oPRN.PrinterStatus)
      Debug.Print IIf(oPRN.workoffline, "Не подключен", "Подключен")
      Debug.Print "Установлен по-умолчанию: "; IIf(oPRN.Default, "да", "нет")
      Debug.Print "Принтер сетевой: "; IIf(oPRN.Network, "да", "нет")
      Debug.Print "============================================================================="
    End If
  End If
Next
Set oPRN = Nothing
End Sub
2) Полный перечень параметров:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
Option Explicit
'CopyPaste from Scriptomatic :)
Const wbemFlagReturnImmediately As Long = &H10
Const wbemFlagForwardOnly As Long = &H20
 
Sub Show_Printer_Instances_Info()
Dim objWMIService As Object, colItems As Object, objItem
   Set objWMIService = GetObject("WinMgmts:{ImpersonationLevel=Impersonate}!//./root/CIMV2")
   Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Printer", "WQL", _
                                          wbemFlagReturnImmediately + wbemFlagForwardOnly)
   For Each objItem In colItems
 
'Название моего принтера !!! (LBP 2900)
   If InStr(objItem.Name, "LBP") <> 0 Then
      Debug.Print "Attributes: " & objItem.Attributes
      Debug.Print "Availability: " & objItem.Availability
      Debug.Print "AvailableJobSheets: " & WMIJoin(objItem.AvailableJobSheets, ",")
      Debug.Print "AveragePagesPerMinute: " & objItem.AveragePagesPerMinute
      Debug.Print "Capabilities: " & WMIJoin(objItem.Capabilities, ",")
      Debug.Print "CapabilityDescriptions: " & WMIJoin(objItem.CapabilityDescriptions, ",")
      Debug.Print "Caption: " & objItem.Caption
      Debug.Print "CharSetsSupported: " & WMIJoin(objItem.CharSetsSupported, ",")
      Debug.Print "Comment: " & objItem.Comment
      Debug.Print "ConfigManagerErrorCode: " & objItem.ConfigManagerErrorCode
      Debug.Print "ConfigManagerUserConfig: " & objItem.ConfigManagerUserConfig
      Debug.Print "CreationClassName: " & objItem.CreationClassName
      Debug.Print "CurrentCapabilities: " & WMIJoin(objItem.CurrentCapabilities, ",")
      Debug.Print "CurrentCharSet: " & objItem.CurrentCharSet
      Debug.Print "CurrentLanguage: " & objItem.CurrentLanguage
      Debug.Print "CurrentMimeType: " & objItem.CurrentMimeType
      Debug.Print "CurrentNaturalLanguage: " & objItem.CurrentNaturalLanguage
      Debug.Print "CurrentPaperType: " & objItem.CurrentPaperType
      Debug.Print "Default: " & objItem.Default
      Debug.Print "DefaultCapabilities: " & WMIJoin(objItem.DefaultCapabilities, ",")
      Debug.Print "DefaultCopies: " & objItem.DefaultCopies
      Debug.Print "DefaultLanguage: " & objItem.DefaultLanguage
      Debug.Print "DefaultMimeType: " & objItem.DefaultMimeType
      Debug.Print "DefaultNumberUp: " & objItem.DefaultNumberUp
      Debug.Print "DefaultPaperType: " & objItem.DefaultPaperType
      Debug.Print "DefaultPriority: " & objItem.DefaultPriority
      Debug.Print "Description: " & objItem.Description
      Debug.Print "DetectedErrorState: " & objItem.DetectedErrorState
      Debug.Print "DeviceID: " & objItem.DeviceID
      Debug.Print "Direct: " & objItem.Direct
      Debug.Print "DoCompleteFirst: " & objItem.DoCompleteFirst
      Debug.Print "DriverName: " & objItem.DriverName
      Debug.Print "EnableBIDI: " & objItem.enablebidi
      Debug.Print "EnableDevQueryPrint: " & objItem.EnableDevQueryPrint
      Debug.Print "ErrorCleared: " & objItem.ErrorCleared
      Debug.Print "ErrorDescription: " & objItem.ErrorDescription
      Debug.Print "ErrorInformation: " & WMIJoin(objItem.ErrorInformation, ",")
      Debug.Print "ExtendedDetectedErrorState: " & objItem.ExtendedDetectedErrorState
      Debug.Print "ExtendedPrinterStatus: " & objItem.ExtendedPrinterStatus
      Debug.Print "Hidden: " & objItem.Hidden
      Debug.Print "HorizontalResolution: " & objItem.HorizontalResolution
      Debug.Print "InstallDate: " & WMIDateStringToDate(objItem.InstallDate)
      Debug.Print "JobCountSinceLastReset: " & objItem.JobCountSinceLastReset
      Debug.Print "KeepPrintedJobs: " & objItem.KeepPrintedJobs
      Debug.Print "LanguagesSupported: " & WMIJoin(objItem.LanguagesSupported, ",")
      Debug.Print "LastErrorCode: " & objItem.LastErrorCode
      Debug.Print "Local: " & objItem.Local
      Debug.Print "Location: " & objItem.Location
      Debug.Print "MarkingTechnology: " & objItem.MarkingTechnology
      Debug.Print "MaxCopies: " & objItem.MaxCopies
      Debug.Print "MaxNumberUp: " & objItem.MaxNumberUp
      Debug.Print "MaxSizeSupported: " & objItem.MaxSizeSupported
      Debug.Print "MimeTypesSupported: " & WMIJoin(objItem.MimeTypesSupported, ",")
      Debug.Print "Name: " & objItem.Name
      Debug.Print "NaturalLanguagesSupported: " & WMIJoin(objItem.NaturalLanguagesSupported, ",")
      Debug.Print "Network: " & objItem.Network
      Debug.Print "PaperSizesSupported: " & WMIJoin(objItem.PaperSizesSupported, ",")
      Debug.Print "PaperTypesAvailable: " & WMIJoin(objItem.PaperTypesAvailable, ",")
      Debug.Print "Parameters: " & objItem.Parameters
      Debug.Print "PNPDeviceID: " & objItem.PNPDeviceID
      Debug.Print "PortName: " & objItem.PortName
      Debug.Print "PowerManagementCapabilities: " & WMIJoin(objItem.PowerManagementCapabilities, ",")
      Debug.Print "PowerManagementSupported: " & objItem.PowerManagementSupported
      Debug.Print "PrinterPaperNames: " & WMIJoin(objItem.PrinterPaperNames, ",")
      Debug.Print "PrinterState: " & objItem.PrinterState
      Debug.Print "PrinterStatus: " & objItem.PrinterStatus
      Debug.Print "PrintJobDataType: " & objItem.PrintJobDataType
      Debug.Print "PrintProcessor: " & objItem.PrintProcessor
      Debug.Print "Priority: " & objItem.Priority
      Debug.Print "Published: " & objItem.Published
      Debug.Print "Queued: " & objItem.Queued
      Debug.Print "RawOnly: " & objItem.RawOnly
      Debug.Print "SeparatorFile: " & objItem.SeparatorFile
      Debug.Print "ServerName: " & objItem.ServerName
      Debug.Print "Shared: " & objItem.Shared
      Debug.Print "ShareName: " & objItem.ShareName
      Debug.Print "SpoolEnabled: " & objItem.SpoolEnabled
      Debug.Print "StartTime: " & WMIDateStringToDate(objItem.StartTime)
      Debug.Print "Status: " & objItem.Status
      Debug.Print "StatusInfo: " & objItem.StatusInfo
      Debug.Print "SystemCreationClassName: " & objItem.SystemCreationClassName
      Debug.Print "SystemName: " & objItem.SystemName
      Debug.Print "TimeOfLastReset: " & WMIDateStringToDate(objItem.TimeOfLastReset)
      Debug.Print "UntilTime: " & WMIDateStringToDate(objItem.UntilTime)
      Debug.Print "VerticalResolution: " & objItem.VerticalResolution
      Debug.Print "WorkOffline: " & objItem.workoffline
      Debug.Print
   End If
   Next
 
Set objWMIService = Nothing
Set colItems = Nothing
End Sub
 
Function WMIDateStringToDate(ByVal dtmDate) As Date
If Not IsNull(dtmDate) Then
    WMIDateStringToDate = CDate(Mid$(dtmDate, 5, 2) & "/" & _
    Mid$(dtmDate, 7, 2) & "/" & Left$(dtmDate, 4) _
    & " " & Mid$(dtmDate, 9, 2) & ":" & Mid$(dtmDate, 11, 2) & ":" & Mid$(dtmDate, 13, 2))
End If
End Function
 
Function WMIJoin(ByVal Stri, ByVal Delim$)
If Not IsNull(Stri) Then
     WMIJoin = Join(Stri, Delim)
End If
End Function
За "вне сети" отвечает параметр "workoffline".
Также интересен "Attributes", если его распарсить согласно числовым константам.

А вот сравнительный анализ атрибутов "Реального" и "Виртуального" принтера (3 раза клацните, чтобы увидеть в нормальном качестве).
Делайте выводы.
Миниатюры
Выяснить сколько доступных для печати принтеров и их марку   Выяснить сколько доступных для печати принтеров и их марку  
3
призрак
 Аватар для ikki
3266 / 894 / 119
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
22.09.2012, 12:00
Лучший ответ Сообщение было отмечено как решение

Решение

у кого много-много принтеров,
потестируйте?

Visual Basic
1
2
3
4
5
6
7
Sub ПолучениеСпискаПринтеров()
     Set AllPrinters = GetObject("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_Printer", , 48)
     For Each printer In AllPrinters
        n = n + 1: Debug.Print "Принтер №" & n & ": " & printer.Name
     Next
     Debug.Print "Всего принтеров: " & n
End Sub
Visual Basic
1
2
3
4
5
6
7
8
9
10
Sub ПолучениеСпискаПринтеров_версия2()
     With CreateObject("Shell.Application").NameSpace(4).Items
         For n = 1 To .Count - 1
             Debug.Print "Принтер №" & n & ": " & .Item(n).Name
             Debug.Print vbTab & "Путь к принтеру №" & n & ": " & .Item(n).Path
         Next
         Debug.Print "Всего принтеров: " & .Count - 1
     End With
     Debug.Print "Активный принтер: " & Application.ActivePrinter
End Sub
Visual Basic
1
2
3
4
5
6
7
8
9
Sub ВыводСпискаИмёнДоступныхПринтеров()
     Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
     Set colItems = objWMIService.ExecQuery _
                    ("SELECT * FROM Win32_Printer WHERE PrinterStatus = '3'")
 
     For Each PRN In colItems
         Debug.Print PRN.name
     Next
End Sub
автор всех трёх процедур: EducatedFool
пс. считаю, что надо бы дать ссылку на сайт автора, но, емнип, неправильные правила данного форума это не разрешают
3
1712 / 579 / 76
Регистрация: 10.04.2009
Сообщений: 9,327
22.09.2012, 14:18  [ТС]
спасибо!!!, выглядит хоть не страшно, про товарища

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Option Explicit '- не забываем
 
Sub ПолучениеСпискаПринтеров()
 
     Dim AllPrinters As Object
     Set AllPrinters = GetObject("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_Printer", , 48)
     
     Dim printer As Object
     Dim n As Long
     
     For Each printer In AllPrinters
        n = n + 1: Debug.Print "Принтер №" & n & ": " & printer.name
     Next
     
     Debug.Print "Всего принтеров: " & n
     
End Sub
 
Sub ВыводСпискаИмёнДоступныхПринтеров()
 
     Dim objWMIService As Object
     Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
     
     Dim colItems As Object
     Set colItems = objWMIService.ExecQuery _
                    ("SELECT * FROM Win32_Printer WHERE PrinterStatus = '3'")
 
     Dim PRN As Object
     For Each PRN In colItems
         Debug.Print PRN.name
     Next
     
End Sub
а, второй код, что-то объявил переменную и он потух, на строке
Visual Basic
1
Debug.Print "Принтер №" & n & ": " & .Item(n).name
- ошибка 455
445 Object doesn't support this action Эта команда не поддерживается указанным объектом
???
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Sub ПолучениеСпискаПринтеров_версия2()
 
     With CreateObject("Shell.Application").NameSpace(4).Items
         
         Dim n As Long
         For n = 1 To .Count - 1
             Debug.Print "Принтер №" & n & ": " & .Item(n).name
             Debug.Print vbTab & "Путь к принтеру №" & n & ": " & .Item(n).Path
         Next
         Debug.Print "Всего принтеров: " & .Count - 1
     End With
     Debug.Print "Активный принтер: " & Application.ActivePrinter
     
End Sub
0
призрак
 Аватар для ikki
3266 / 894 / 119
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
22.09.2012, 15:34
Ципихович Эндрю, а с какого перепугу вы решили, что там именно Long нужен?
покажите описание объекта, которым вы руководствовались.
честно говоря, не понимаю, зачем корёжить работающий код.
0
1712 / 579 / 76
Регистрация: 10.04.2009
Сообщений: 9,327
22.09.2012, 15:46  [ТС]
Цитата Сообщение от Ципихович Эндрю Посмотреть сообщение
про товарища Option Explicit '- не забываем
Цитата Сообщение от ikki Посмотреть сообщение
а с какого перепугу вы решили, что там именно Long нужен
а что нужно в цикле? в этом случае?
0
призрак
 Аватар для ikki
3266 / 894 / 119
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
22.09.2012, 16:30
Ципихович Эндрю, ну попробуйте объявить переменную без указания типа - будет Variant.
я бы и сам проверил, но у меня дома нет принтеров. даже виртуальных.
0
1712 / 579 / 76
Регистрация: 10.04.2009
Сообщений: 9,327
22.09.2012, 16:36  [ТС]
Цитата Сообщение от ikki Посмотреть сообщение
Variant
это мы всегда успеем и он прошёл, просто хотел посоветоваться, спасибо
0
5472 / 1150 / 50
Регистрация: 15.09.2012
Сообщений: 3,576
15.03.2013, 22:06
Существуют несколько видов портов.
С помощью библиотеки "winmgmts" я получил порт принтера: "XPSPort:". А программа "Excel" выдаёт вот такое: "Microsoft XPS Document Writer (Ne00:)".

Т.е. получается средствами библиотеки "winmgmts" нельзя получить нужное название порта для того, чтобы печатать через "Excel"?
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
15.03.2013, 22:28
У меня Excel выдает именно порт "XPSPort:"

P.S. "winmgmts" - это служба или в данном случае моникер WMI в составе запроса (через него мы получаем доступ к инструментарию).

Порт вида Ne00: нужен для печати по сети.
Изображения
 
0
5472 / 1150 / 50
Регистрация: 15.09.2012
Сообщений: 3,576
15.03.2013, 22:34
Dragokas, вот так я получил порт из "Excel":
Visual Basic
1
Application.Activeprinter
Сейчас в интернете читал, но не пробовал, пишут, что можно по имени принтера печатать (без указания порта) в команде PrintOut.

Но хотелось бы всё-так получить простое решение, чтобы менять активный принтер в программе "Excel". Это нужно для того, чтобы после выбора принтера, перед печатью проверить: не изменились ли разрывы страниц в Excel-книге, т.к. Excel-книга подстраивается под принтер по умолчанию или под принтер, на который печатали последний раз. Для одного принтера разрывы страниц будут находиться в одном месте, а для другого - в другом (такое редко бывает, но бывает).
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
16.03.2013, 02:14
Лучший ответ Сообщение было отмечено как решение

Решение

Скрипт, в нужном Вам виде информацию возвращает API-функция EnumPrinters.
Готовая реализация находится в теме Изменение настроек выбранного принтера Excel из VBA
Модуль называется PrinterFind_EnumPrinters. Тестовый запуск - через Private Sub Test()

Добавлено через 34 минуты
Да, так и есть PrintOut может работать без указания порта.

Visual Basic
1
2
3
'http://msdn.microsoft.com/ru-ru/library/microsoft.office.tools.excel.worksheet.printout.aspx
Application.Worksheets(1).PrintOut From:=1, To:=1, Copies:=1, Preview:=False, _
    ActivePrinter:="Microsoft XPS Document Writer", PrintToFile:=False, Collate:=False, PrToFileName:=vbNullString
При указании несуществующего принтера, печать будет продолжена на принтере, выставленном по-умолчанию.
Возможно, при переразметке страницы имеет смысл установить свойство Preview (предварительный просмотр) в true.

В любом случае порядок нумерации сетевых портов идет в том же порядке, как и получение списка принтеров через WMI. Т.е. Вы можете смело завести самостоятельно счетчик с 0, например, в моем коде (пост № 6) строки №№ 27,28,36,37 закомментировать и получите тоже самое значение, добавив префикс Ne.

application.activeprinter в роле Write-свойства наоборот может принимать только имя принтера с портом вида NeXX:
0
5472 / 1150 / 50
Регистрация: 15.09.2012
Сообщений: 3,576
16.03.2013, 15:14
Пункт 1

Цитата Сообщение от Dragokas Посмотреть сообщение
Скрипт, в нужном Вам виде информацию возвращает API-функция EnumPrinters.
Кликните здесь для просмотра всего текста
API-функция "EnumPrinters" возвращает данные в виде числа (или чисел). Поэтому при использовании API-функции "EnumPrinters", нужно применить ещё две API-функции, чтобы расшифровать эти числа. Кроме того, функция "EnumPrinters" возвращает имя порта в таком же виде, как и библиотека "WinMgmts". Т.е. для моей задачи API-функция "EnumPrinters" не подходит.
В этом примере: Изменение настроек выбранного принтера Excel из VBA - автор темы показывает только как получить список имён принтеров с помощью API-функции "EnumPrinters" и не показывает, как получить список портов принтеров.

Имя порта в нужном виде для программы "Excel" можно получить с помощью API-функции "GetProfileString". Может быть это единственный вариант получения имя порта принтера в нужном для программы "Excel" виде. Только "GetProfileString" является старой и осталась в "Windows" для совместимости с 16-разрядными версиями "Windows".

Я прихожу к выводу, что VBA-Excel-команда "Activeprinter" использует старый способ доступа к операционной системе "Windows". VBA-Excel-команда "Activeprinter" берёт данные из "Windows" с помощью файла инициализации "WIN.INI" (не знаю, что это такое). Но в новых версиях "Windows" уже не используется файл инициализации "WIN.INI". Вместо файла инициализации "WIN.INI" используется Windows-реестр.



Пункт 2

Цитата Сообщение от Dragokas Посмотреть сообщение
Возможно, при переразметке страницы имеет смысл установить свойство Preview (предварительный просмотр) в true.
Кликните здесь для просмотра всего текста
опишите более подробно, как можно использовать то, что вы предлагаете, в данной задаче?
Напомню задачу: после смены активного принтера, нужно проверить: не изменилось ли расположение разрывов страниц. Ещё раз напомню, что положение разрывов страниц привязано к активному принтеру.



Пункт 3

Цитата Сообщение от Dragokas Посмотреть сообщение
В любом случае порядок нумерации сетевых портов идет в том же порядке, как и получение списка принтеров через WMI. Т.е. Вы можете смело завести самостоятельно счетчик с 0, например, в моем коде (пост № 6) строки №№ 27,28,36,37 закомментировать и получите тоже самое значение, добавив префикс Ne.
Кликните здесь для просмотра всего текста
Вот получаю имя и порт принтера:
Visual Basic
1
2
3
4
5
6
Sub Procedure_2()
    
    'Вывод в View - Immediate Window.
    Debug.Print Application.ActivePrinter
 
End Sub
Результат: doPDF v7 (DOP7

Как мне, используя ваше предложение, заменить имя порта "DOP7:" на имя порта со словом "Ne"?



Пункт 4

Алгоритм установки активного принтера в программе "Excel" без использования API-функций и не указывая имя порта.

Кликните здесь для просмотра всего текста
Может быть по такому алгоритму попробовать менять в программе "Excel" активный принтер без использования API-функций и не указывая имя порта принтера (имя порта принтера в программе "Excel" отличается от имени порта, который можно увидеть где-нибудь в другом месте).
  1. вот так получаем список имён принтеров (вроде несложный код):
    Кликните здесь для просмотра всего текста
    Visual Basic
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    Sub Procedure_1()
        
        'Нужно подключить библиотеку:
        'Tools - References... - Microsoft Shell Controls and Automation.
        Dim myShell As New Shell32.Shell
        Dim myFolder As Shell32.Folder
        Dim myItems As Shell32.FolderItems
        Dim myItem As Shell32.FolderItem
        
        '1. Даём папке с принтерами VBA-имя "myFolder".
            'С помощью "Shell" папка с принтерами находится в Windows
            'под номером "4".
        Set myFolder = myShell.Namespace(4)
        
        '2. Даём VBA-имя "myItems" содержимому папки с принтерами.
        Set myItems = myFolder.Items
        
        '3. Выводим в View - Immediate Window имена всех принтеров.
        For Each myItem In myItems
            Debug.Print myItem.Name
        Next myItem
     
    End Sub
  2. создаём новую Excel-книгу;
  3. запускаем первый лист новой Excel-книги на печать:
    Visual Basic
    1
    2
    3
    4
    5
    
    Sub Procedure_1()
     
        ActiveSheet.PrintOut ActivePrinter:="doPDF v7"
     
    End Sub
    лист пустой и ничего не произойдёт, а активный принтер сменится.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18033 / 7736 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
21.03.2013, 03:13
1) Да, верно. Нужен GetProfileString. Исходник Bagir-а сбил с толку. Там Sub Test был привязан к другому модулю - "PrinterFind_GetProfileString", в котором и написан пример с этой API для получения портов.
WIN.INI - это файл в c:\windows. В новых системах все еще присутствует для совместимости.

2) Свойство Preview. Код выше.
Либо установить свойство:
Visual Basic
1
application.Activeprinter = "Правильный принтер"
Затем перейти в режим разметки страницы:
Visual Basic
1
ActiveWindow.View = xlPageBreakPreview
Ну а проверить не изменились ли разрывы страниц, можно предварительно куда-нибуть сохранив эти значения:
Visual Basic
1
2
3
for n = 0 to ActiveSheet.HPageBreaks.Count
    debug.? n; ActiveSheet.HPageBreaks(n).Location.address(0,0)
next
Потом в обратном порядке можно проверить их.

3) Был неправ. Там специфические правила назначений портов. Через счетчик не получится.

4) Можно. Требуется эксперимент. Как Вы думаете, переразметка произойдет автоматически? Ведь этот код идет в противовес Вашему желанию все проверить перед началом печати.

Пункт 5.
Честно, никогда еще не сталкивался с явлением, когда разметка меняется при печати на разных принтерах.
Думаю, следует поставить эксперимент, когда это происходит и какие условия нужно соблюсти:
1) войти в режим разметки при установленном новом активном принтере достаточно ли?
2) а если установлена пользовательская разметка для некоторых листов?
3) если выставлен не 100% масштаб...
0
5472 / 1150 / 50
Регистрация: 15.09.2012
Сообщений: 3,576
21.03.2013, 07:37
По пункту 2

Такой алгоритм я и придумал: сохраняю данные о разрывах страниц в массивах, если пользователь изменяет принтер, то собираю новые данные о разрывах страниц. Затем сравниваю два массива.


По пункту 4

Цитата Сообщение от Dragokas Посмотреть сообщение
Можно. Требуется эксперимент. Как Вы думаете, переразметка произойдет автоматически? Ведь этот код идет в противовес Вашему желанию все проверить перед началом печати.
Кликните здесь для просмотра всего текста
если свойства принтеров сильно отличаются (например, большая разница между виртуальными и реальными принтерами), то переразметка может произойти. Этот код не идёт в противовес. Ведь при распечатки пустого листа ничего не произойдёт. Просто закрываем новую книгу и делаем то, что нужно. Только вдруг что-то не так пойдёт и макрос будет печатать не на тот принтер - в этом риск.


По пункту 5

Честно, никогда еще не сталкивался с явлением, когда разметка меняется при печати на разных принтерах.
Кликните здесь для просмотра всего текста
Чтобы столкнуться с этим явлением, нужно:
  1. часто распечатывать что-то на принтер;
  2. иметь разные принтера.
Если вы хотите убедиться в этом, то создайте Excel-книгу и сделайте в ней данные впритык страницам, а затем меняйте принтеры. Не всегда разметка будет изменена, но можно получить результат, что разметка страниц изменится.

Переразметка происходит автоматически при выборе принтера, а не при изменении настроек программы "Excel". Так запрограммировано программистами из организации "Microsoft", что книги-Excel подстариваются под принтер по умолчанию. Поэтому у пользователя выбора нет: хочет пользователь или нет, книга-Excel будет подстраиваться под принтер по умолчанию, даже если пользователь ничего и никогда не печатает.

Может быть есть ещё и другие настройки, которые влияют на разметку Excel-книг.
0
5472 / 1150 / 50
Регистрация: 15.09.2012
Сообщений: 3,576
21.03.2013, 07:51
Я выложил книгу, с помощью которой можно посмотреть, что разметка Excel-книги меняется при смене принтера.
Для тестирования нужны два виртуальных принтера (они бесплатные): "doPDF v7" и "Microsoft XPS Document Viewer".

Если вы откроете книгу, что я выложил, и будете изменять принтер (в "Excel 2010" принтер можно так изменить: вкладка Главная - Печать - Принтер - выберие принтер - вкладка Главная), то количество страниц, которое должно распечаться, будет меняться (в режиме "Страничный" синие линии будут меняться).
Вложения
Тип файла: zip Разметка страниц.zip (5.7 Кб, 19 просмотров)
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.03.2013, 07:51
Помогаю со студенческими работами здесь

Обеспечение печати 2 принтеров
Помогите решить проблему , нужно обеспечить печать на 2 принтера причем одновременно, подскажите как это сделать либо программу если такая...

Как получить список принтеров и очистить очередь печати выбранного принтера?
Как получить список принтеров и очистить очередь печати выбранного принтера? Вторая часть &quot;Очистить очередь печати&quot;...

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

Для двух заданных чисел выяснить, какое из них больше и на сколько
Добрый день,Помогите написать программу на языке Паскаль обработки натуральных чисел с возможным числом разрядов больше 10 согласно...

Для каждого из чисел, входящих в последовательность, выяснить, сколько раз оно в нее входит
Даны целые числа a1,a2,...,an. Для каждого из чисел, входящих в последовательность a1,a2,...,an, выяснить, сколько раз оно входит в эту...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru