VBA로 현재 프린터 단면/양면 인쇄 설정
이번 미션은 엑셀에서 시트이름이 '양면3'이면 양면 3부 인쇄, '단면1'이면 단면 1부로 모든 엑셀 시트를 한꺼번에 일괄 인쇄하는 것입니다.
VBA로 원하는 인쇄 매수대로 인쇄하는 것은 쉬우나
양면 인쇄는 VBA로도 설정하기 까다롭습니다.
한 가지 방법은 프린터를 하나 더 추가한 다음 양면으로 설정하고
단면일 때는 프린터1을 현재 프린터(ActivePrinter)로 설정하고
양면일 때는 프린터2를 현재 프린터(ActivePrinter)로 설정하는 방법이 있습니다.
여기서는 이 방법대신 새로운 프린터를 설정할 필요 없이 API를 이용해서 그때마다 양면/단면을 설정해서 인쇄하는 방법을 모색합니다.
아래와 같은 코드를 참고하였습니다.
- VBA7 환경(오피스2010이상)
- VB6 하위버전(~오피스2010이전)
윈도우 API를 이용한 위 코드를 활용 및 수정했습니다.
그런데 넘어야할 문제점이 많습니다.
먼저 위 코드를 활용해도 양면 설정이 현재 프린터에 반영이 되지 않습니다.
>> 임시로 다른 PDF프린터로 현재 프린터로 설정했다가
다시 원래 프린터로 설정해서 양면/단면 설정이 반영되도록 합니다.
따라서 임시로 다른 프린터로 설정하기 위해 시스템에 PDF프린터가 설치되어 있어야 합니다.
없다면 nPDF 등의 가상 PDF 프린터를 설치하세요.
현재 프린터는 양면 인쇄를 지원하는 프린터여야 합니다.
PDF프린터는 가상 프린터이므로 양면을 지원하지 않습니다.
Alt+F8 누르고 myPrint 매크로를 실행하면 됩니다.
숨겨진 시트는 인쇄에서 제외합니다.
인쇄 후에는 단면/양면 원래 설정을 복구합니다.
시트 이름이 '양면2' 처럼 이름이 겹칠 수 없기 때문에 문제가 생깁니다.
>> '양면2 설명1' 처럼 빈칸 다음에 설명을 추가하면 시트 이름이 달라져 같은 방식 인쇄가 중복되어도 됩니다.
Module1:
Option Explicit
' 시트이름이 '양면3'이면 양면 3부 인쇄, '단면1'이면 단면 1부 인쇄
' *************************************
' *** 기본 프린터 설정 후 실행 ***
' *** 시스템에 PDF 프린터 설치 필요 ***
' *************************************
Sub myPrint()
Dim sht As Worksheet
Dim str As String, p As Integer, ret As Boolean, iDuplex As Long
iDuplex = GetDuplex
'sht.PageSetup.PaperSize = xlPaperA4
'sht.PageSetup.FitToPagesTall
For Each sht In ActiveWorkbook.Worksheets
If sht.Visible = xlSheetVisible Then
str = sht.name
If InStr(str, " ") > 0 Then str = Left(str, InStr(str, " ") - 1)
If str Like "?면*" Then
'페이지수
On Error Resume Next
p = Int(Mid(str, 3))
On Error GoTo 0
If p = 0 Then p = 1
'단면/양면
If sht.name Like "양면*" Then
ret = SetActiveDuplex(2) '2: 긴면 묶음, 3: 짧은면 묶음
Else
ret = SetActiveDuplex(1)
End If
DoEvents
If ret = False Then _
If MsgBox("양면/단면 설정이 실패했습니다! 계속할까요?", vbCritical + vbOKCancel) = vbCancel Then _
Exit For
'인쇄
sht.PrintOut Copies:=p
End If
End If
Next sht
SetActiveDuplex iDuplex
End Sub
오피스2010이상인 경우와 미만인 경우를 반영하기 위해
#IF VBA7 이 사용되었습니다.
또한 오피스2010에서도 작동하고 2021이나 365에서도 작동하도록 여러가지 상황을 고려하느라 많은 테스트와 수정작업이 필요했습니다. Type 선언에 따라 특정 시스템에서 엑셀이 말없이 종료되는 현상이 여러번 발생했습니다.
Module2:
'https://answers.microsoft.com/en-us/msoffice/forum/all/set-duplex-printing-for-word-automation-for-vba7/994416cc-bca4-4f68-971d-27332b826a12
'https://web.archive.org/web/20030225011214/http://support.microsoft.com:80/?kbid=230743
'http://www.lessanvaezi.com/changing-printer-settings-using-the-windows-api/
Option Explicit
#If VBA7 Then
'constants form DEVMODE structure
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
Public Type DEVMODE
dmDeviceName(0 To CCHDEVICENAME - 1) As Byte
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName(0 To CCHFORMNAME - 1) As Byte
dmUnusedPadding As Integer
dmBitsPerPel As Long
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long '#if(WINVER >= 0x0400)
dmICMMethod As Long
dmICMIntent As Long
dmMediaType As Long
dmDitherType As Long
dmReserved1 As Long
dmReserved2 As Long ' #if (WINVER >= 0x0500) || (_WIN32_WINNT >= _WIN32_WINNT_NT4)
dwPanningWidth As Long
dwPanningHeight As Long ' #endif#endif /* WINVER >= 0x0400 */
End Type
Public Type PRINTER_DEFAULTS
pDatatype As String
pDevmode As LongPtr 'DEVMODE
DesiredAccess As Long
End Type
' Public Type PRINTER_INFO_2
' pServerName As String
' pPrinterName As String
' pShareName As String
' pPortName As String
' pDriverName As String
' pComment As String
' pLocation As String
' pDevmode As LongPtr 'DEVMODE
' pSepFile As String
' pPrintProcessor As String
' pDatatype As String
' pParameters As String
' pSecurityDescriptor As LongPtr 'SECURITY_DESCRIPTOR
' Attributes As Long
' Priority As Long
' DefaultPriority As Long
' StartTime As Long
' UntilTime As Long
' Status As Long
' cJobs As Long
' AveragePPM As Long
' End Type
Public Type PRINTER_INFO_2
pServerName As LongPtr
pPrinterName As LongPtr
pShareName As LongPtr
pPortName As LongPtr
pDriverName As LongPtr
pComment As LongPtr
pLocation As LongPtr
pDevmode As LongPtr 'Pointer to DEVMODE
pSepFile As LongPtr
pPrintProcessor As LongPtr
pDatatype As LongPtr
pParameters As LongPtr
pSecurityDescriptor As LongPtr 'Pointer to SECURITY_DESCRIPTOR
Attributes As LongPtr
Priority As LongPtr
DefaultPriority As LongPtr
StartTime As LongPtr
UntilTime As LongPtr
Status As LongPtr
cJobs As LongPtr
AveragePPM As LongPtr
End Type
Public Declare PtrSafe Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As LongPtr, pDefault As PRINTER_DEFAULTS) As Long
Public Declare PtrSafe Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
Public Declare PtrSafe Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hwnd As LongPtr, ByVal hPrinter As LongPtr, ByVal pDeviceName As String, ByVal pDevModeOutput As LongPtr, ByVal pDevModeInput As LongPtr, ByVal fMode As Long) As Long
Public Declare PtrSafe Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As LongPtr, ByVal Level As Long, pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As Long
Public Declare PtrSafe Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As LongPtr, ByVal Level As Long, pPrinter As Byte, ByVal Command As Long) As Long
Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
'constants form DEVMODE structure
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
Public Type DEVMODE
dmDeviceName As String * CCHDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCHFORMNAME
dmLogPizels As Integer
dmBitsPerPel As Long
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
dmICMMethod As Long
dmICMIntent As Long
dmMediaType As Long
dmDitherType As Long
dmReserved1 As Long
dmReserved2 As Long
End Type
Public Type PRINTER_DEFAULTS
pDatatype As Long
pDevmode As Long
DesiredAccess As Long
End Type
Public Type PRINTER_INFO_2
pServerName As Long
pPrinterName As Long
pShareName As Long
pPortName As Long
pDriverName As Long
pComment As Long
pLocation As Long
pDevmode As Long ' Pointer to DEVMODE
pSepFile As Long
pPrintProcessor As Long
pDatatype As Long
pParameters As Long
pSecurityDescriptor As Long ' Pointer to SECURITY_DESCRIPTOR
Attributes As Long
Priority As Long
DefaultPriority As Long
StartTime As Long
UntilTime As Long
Status As Long
cJobs As Long
AveragePPM As Long
End Type
Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long
Public Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hwnd As Long, ByVal hPrinter As Long, ByVal pDeviceName As String, pDevModeOutput As Long, pDevModeInput As Long, ByVal fMode As Long) As Long
Public Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As Long
Public 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
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
#End If
'Access levels for interacting with a device
Const DELETE = &H10000
Const READ_CONTROL = &H20000 ' Read device information
Const WRITE_DAC = &H40000 ' Write Device Access Control info
Const WRITE_OWNER = &H80000 ' Change the object owner
' Combining these for full access to the device
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const PRINTER_ACCESS_USE = &H8
Const PRINTER_NORMAL_ACCESS = (READ_CONTROL Or PRINTER_ACCESS_USE)
Const DM_ORIENTATION = &H1
Const DM_PAPERSIZE = &H2
Const DM_PAPERLENGTH = &H4
Const DM_PAPERWIDTH = &H8
Const DM_DEFAULTSOURCE = &H200
Const DM_PRINTQUALITY = &H400
Const DM_COLOR = &H800
Const DM_DUPLEX = &H1000
Const DM_IN_BUFFER = 8
Const DM_OUT_BUFFER = 2
Private Sub test_SetActiveDuplex()
Debug.Print SetActiveDuplex(2)
End Sub
Function SetActiveDuplex(iDuplex As Long) As Boolean
Dim dPrinter As String, tPrinter As String
Dim ret As Long
dPrinter = getActivePrinter(True)
tPrinter = FindPrinter("PDF")
'Debug.Print getActivePrinter
ret = SetPrinterProperty(DM_DUPLEX, iDuplex) '1: simplex, 2: duplex/long side binding, 3: duplex/ short side binding
Application.ActivePrinter = tPrinter
Application.ActivePrinter = dPrinter
ret = GetPrinterProperty(DM_DUPLEX)
If ret = iDuplex Then SetActiveDuplex = True Else SetActiveDuplex = False
End Function
Public Function SetDuplex(iDuplex As Long) As Boolean
SetDuplex = SetPrinterProperty(DM_DUPLEX, iDuplex)
End Function
Public Function GetDuplex() As Long
GetDuplex = GetPrinterProperty(DM_DUPLEX)
End Function
Public Sub SetPrintQuality(iQuality As Long)
SetPrinterProperty DM_PRINTQUALITY, iQuality ' -1: Draft, -2: Low, -3:Medium, -4: High, int(300): dpi
End Sub
Public Function GetPrintQuality() As Long
GetPrintQuality = GetPrinterProperty(DM_PRINTQUALITY)
End Function
' ==================================================================
' Set Printer to Duplex by calling SetPrinterProperty
'
' Programmatically set the Duplex flag for the specified printer
' driver's default properties.
'
' Returns: True on success, False on error.
'
' Parameters:
' lngPropertyType - The name of the parameter to be modified (in our case, DM_DUPLEX)
'
' lngPropertyValue - One of the following standard settings (in our case, 2):
' 1 = None
' 2 = Duplex on long edge (book)
' 3 = Duplex on short edge (legal)
'
' ==================================================================
Function SetPrinterProperty(ByVal lngPropertyType As Long, ByVal lngPropertyValue As Long) As Boolean
Dim udtPD As PRINTER_DEFAULTS
Dim udtPI As PRINTER_INFO_2
Dim udtDM As DEVMODE
Dim strPrinterName As String
Dim bytDevModeData() As Byte
Dim bytPInfoMemory() As Byte
Dim lngPrinter As LongPtr
Dim lngBytesNeeded As Long
Dim lngReturn As Long
Dim lngJunk As Long
On Error GoTo err_exit
'this defines the printer we want to use. You may want to adjust this to Your needs
'Samsung MLXXXX Series on LPT1:
'Ne01:에 있는 Samsung MLXXXX Series (192.168.0.xxx)
strPrinterName = getActivePrinter
'You may have to use...
'Trim$ (Left$(ActivePrinter, InStr(ActivePrinter, " on ")))
'...here in case the name of Your printer looks something like this: "
udtPD.DesiredAccess = PRINTER_NORMAL_ACCESS
'Get the printer handle ("lngPrinter")
lngReturn = OpenPrinter(strPrinterName, lngPrinter, udtPD)
If (lngReturn = 0) Or (lngPrinter = 0) Then Exit Function 'Can't access current printer. Bail out doing nothing
'Get the size of the DEVMODE structure to be loaded
lngReturn = DocumentProperties(0, lngPrinter, strPrinterName, 0, 0, 0)
If (lngReturn < 0) Then Err.Raise vbObjectError + 1 'Can't access printer properties.
'Make sure the byte array is large enough
'Some printer drivers lie about the size of the DEVMODE structure they
'return, so an extra 100 bytes is provided just in case!
ReDim bytDevModeData(0 To CLng(lngReturn) + 100) As Byte
'Load the byte array
lngReturn = DocumentProperties(0, lngPrinter, strPrinterName, VarPtr(bytDevModeData(0)), 0, DM_OUT_BUFFER)
If (lngReturn < 0) Then Err.Raise vbObjectError + 2
'Copy the byte array into a structure so it can be manipulated
Call CopyMemory(udtDM, bytDevModeData(0), Len(udtDM))
If udtDM.dmFields And lngPropertyType = 0 Then Err.Raise vbObjectError + 3 'Wanted property not available. Bail out.
'Set the property to the appropriate value
Select Case lngPropertyType
Case DM_ORIENTATION
udtDM.dmOrientation = lngPropertyValue
Case DM_PAPERSIZE
udtDM.dmPaperSize = lngPropertyValue
Case DM_PAPERLENGTH
udtDM.dmPaperLength = lngPropertyValue
Case DM_PAPERWIDTH
udtDM.dmPaperWidth = lngPropertyValue
Case DM_DEFAULTSOURCE
udtDM.dmDefaultSource = lngPropertyValue
Case DM_PRINTQUALITY
udtDM.dmPrintQuality = lngPropertyValue
Case DM_COLOR
udtDM.dmColor = lngPropertyValue
Case DM_DUPLEX
udtDM.dmDuplex = lngPropertyValue
End Select
'Load the structure back into the byte arra
Call CopyMemory(bytDevModeData(0), udtDM, Len(udtDM))
'Tell the printer about the new property, specifying both the DM_IN_BUFFER and DM_OUT_BUFFER values (which are combined using the OR operator)
lngReturn = DocumentProperties(0, lngPrinter, strPrinterName, VarPtr(bytDevModeData(0)), VarPtr(bytDevModeData(0)), DM_IN_BUFFER Or DM_OUT_BUFFER)
If (lngReturn < 0) Then Err.Raise vbObjectError + 4
'The code above *ought* to be sufficient to set the property
'correctly. Unfortunately some brands of Postscript printer don't
'seem to respond correctly. The following code is used to make
'sure they also respond correctly.
Call GetPrinter(lngPrinter, 2, 0, 0, lngBytesNeeded)
If (lngBytesNeeded = 0) Then Err.Raise vbObjectError + 5 'Couldn't access shared printer settings
'Set byte array large enough for PRINTER_INFO_2 structure
ReDim bytPInfoMemory(0 To lngBytesNeeded + 100) As Byte
'Load the PRINTER_INFO_2 structure into byte array
lngReturn = GetPrinter(lngPrinter, 2, bytPInfoMemory(0), lngBytesNeeded, lngJunk)
If (lngReturn = 0) Then Err.Raise vbObjectError + 6 'Couldn't access shared printer settings
'Copy byte array into the structured type
Call CopyMemory(udtPI, bytPInfoMemory(0), Len(udtPI))
'Load the DEVMODE structure with byte array containing
'the new property value
udtPI.pDevmode = VarPtr(bytDevModeData(0))
'Set security descriptor to null
udtPI.pSecurityDescriptor = 0
'Copy the PRINTER_INFO_2 structure back into byte array
Call CopyMemory(bytPInfoMemory(0), udtPI, Len(udtPI))
'Send the new details to the printer
lngReturn = SetPrinter(lngPrinter, 2, bytPInfoMemory(0), 0)
'Indicate whether it all worked or not!
SetPrinterProperty = CBool(lngReturn)
err_exit:
'Release the printer handle
If (lngPrinter <> 0) Then Call ClosePrinter(lngPrinter)
End Function
' ==================================================================
' Find the Printer's Duplex setting by calling GetPrinterProperty
'
' Returns: The number value of the desired setting
'
' Parameters:
' lngPropertyType - The name of the parameter to be modified (in our case, DM_DUPLEX)
'
' ==================================================================
Function GetPrinterProperty(ByVal lngPropertyType As Long) As Long
Dim udtPD As PRINTER_DEFAULTS
Dim udtDM As DEVMODE
Dim strPrinterName As String
Dim bytDevModeData() As Byte
Dim lngPrinter As LongPtr, lngReturn As Long
On Error GoTo err_exit
'this defines the printer we want to use. You may want to adjust this to Your needs
strPrinterName = getActivePrinter
'You may have to use...
'Trim$ (Left$(ActivePrinter, InStr(ActivePrinter, " on ")))
'...here in case the name of Your printer looks something like this: "
udtPD.DesiredAccess = PRINTER_NORMAL_ACCESS
'Get the printer handle ("lngPrinter")
lngReturn = OpenPrinter(strPrinterName, lngPrinter, udtPD)
If (lngReturn = 0) Or (lngPrinter = 0) Then Exit Function
'Get the size of the DEVMODE structure to be loaded
lngReturn = DocumentProperties(0, lngPrinter, strPrinterName, 0, 0, 0)
If (lngReturn < 0) Then Err.Raise vbObjectError + 1 'Can't access printer properties.
'Make sure the byte array is large enough
'Some printer drivers lie about the size of the DEVMODE structure they
'return, so an extra 100 bytes is provided just in case!
ReDim bytDevModeData(0 To CLng(lngReturn) + 100) As Byte
'Load the byte array
lngReturn = DocumentProperties(0, lngPrinter, strPrinterName, VarPtr(bytDevModeData(0)), 0, DM_OUT_BUFFER)
If (lngReturn < 0) Then Err.Raise vbObjectError + 2
'Copy the byte array into a structure so it can be manipulated
Call CopyMemory(udtDM, bytDevModeData(0), Len(udtDM))
If udtDM.dmFields And lngPropertyType = 0 Then Err.Raise vbObjectError + 3 'Wanted property not available. Bail out.
Select Case lngPropertyType
Case DM_ORIENTATION
GetPrinterProperty = udtDM.dmOrientation
Case DM_PAPERSIZE
GetPrinterProperty = udtDM.dmPaperSize
Case DM_PAPERLENGTH
GetPrinterProperty = udtDM.dmPaperLength
Case DM_PAPERWIDTH
GetPrinterProperty = udtDM.dmPaperWidth
Case DM_DEFAULTSOURCE
GetPrinterProperty = udtDM.dmDefaultSource
Case DM_PRINTQUALITY
GetPrinterProperty = udtDM.dmPrintQuality
Case DM_COLOR
GetPrinterProperty = udtDM.dmColor
Case DM_DUPLEX
GetPrinterProperty = udtDM.dmDuplex
End Select
err_exit:
If (lngPrinter <> 0) Then Call ClosePrinter(lngPrinter)
End Function
Function getActivePrinter(Optional Full As Boolean) As String
Dim str As String
str = ActivePrinter
If Full Then
getActivePrinter = str
Exit Function
End If
If InStr(str, " on ") > 0 Then
getActivePrinter = Split(str, " on ")(0)
'Ne01:에 있는 Samsung MLXXXX Series (192.168.0.xxx)
ElseIf InStr(str, "에 있는 ") > 0 Then
getActivePrinter = Split(str, "에 있는 ")(1)
Else
getActivePrinter = str
End If
End Function
Private Sub test_FindPrinter()
FindPrinter "PDF"
End Sub
Function FindPrinter(ByVal PrinterName As String) As String
'This works with Windows 2000 and up
Dim Arr As Variant
Dim Device As Variant
Dim Devices As Variant
Dim Printer As String
Dim RegObj As Object
Dim RegValue As String
Const HKEY_CURRENT_USER = &H80000001
Set RegObj = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
RegObj.EnumValues HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Devices, Arr
For Each Device In Devices
RegObj.GetStringValue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Device, RegValue
'Debug.Print Device
'Printer = Device & " on " & Split(RegValue, ",")(1) 'English
Printer = Split(RegValue, ",")(1) & "에 있는 " & Device 'Korean
'If InStr(1, Printer, PrinterName, vbTextCompare) > 0 Then 'original code
'If StrComp(Device, printerName, vbTextCompare) = 0 Then
If Device Like "*" & PrinterName & "*" Then
FindPrinter = Printer
Exit Function
End If
Next
End Function
테스트만 하려면 test_SetActiveDuplex 에서 인수를 바꿔보세요.
2를 넘기면 양면인쇄(긴면묶기)로 설정하고
3을 넘기면 양면인쇄(짧은면묶기),
1을 넘기면 단면인쇄로 바뀝니다.
엑셀 2010 이상에서 지원합니다.
양면/단면, 프린트 품질, 흑백/칼라, 용지크기, 가로/세로크기, 용지함, 가로/세로 등의 속성도 추가로 설정이 가능합니다.
VBA7이상(2010)인 경우와 이하인 경우를 대비했지만 하위 버전에서는 테스트해보지 못해 작동을 보장하지 못합니다.
프린터 이름 때문에 한글 환경에서만 작동합니다.
영문 윈도우에서는 마지막 FindPrinter에서 프린터 이름이 " on " 이 사용되도록 주석을 수정해야됩니다.
코드 길이에서 보듯이 여러가지조건과 상황을 고려해서 시간을 투자했습니다.
온라인에도 구버전에서 작동하는 코드만 있고 365같은 버전에서도 제대로 작동하는 코드가 없는 상태라 여러가지 시행착오를 거쳐 2010이든 365든 상관없이 작동하도록 이렇게 코드를 올려 놓습니다.