Dành cho những ai cần: điều khiển in 2 mặt giấy bằng VBA Excel

Liên hệ QC

Maika8008

Thành viên gạo cội
Tham gia
12/6/20
Bài viết
4,763
Được thích
5,719
Donate (Momo)
Donate
Giới tính
Nam
Code này tôi sưu tầm để trả lời cho 1 bạn nhưng tôi thấy cần đưa thành 1 bài riêng để tiện cho các thành viên tìm kiếm sử dụng cho công việc khi cần. Tôi đã test thành công ở sub TestIn2Mat: Đặt trạng thái in 2 măt, in tất cả các sheet cần in (với mỗi sheet cứ có trang lẻ là in sang tờ mới), trả lại trạng thái in 1 mặt cho máy in.

Thay tên "Brother MFC-L2700DW" bằng tên máy in 2 mặt của bạn.

Update: theo bác ndu96081631 thì tôi sửa lại khai báo 1 chút và đã test trên Office 32bit. Còn ai dùng 64bit thì cùng tìm cách sử dụng với các hàm khai báo cho 64bit nhé. Tôi không dùng 64bit nên chịu.

PHP:
Public Type PRINTER_INFO_9
    pDevmode As Long '''' POINTER TO DEVMODE
End Type

Public Type DEVMODE
    dmDeviceName As String * 32
    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 * 32
    dmUnusedPadding As Integer
    dmBitsPerPel As Integer
    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 Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, buffer As Long, ByVal pbSize As Long, pbSizeNeeded As Long) As Long
Public Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal Command 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, _
                                                                                            ByVal pDevModeOutput As Long, ByVal pDevModeInput As Long, _
                                                                                            ByVal fMode As Long) As Long

'---------- Khai bao 64 bit
Private Declare PtrSafe Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As LongPtr, pDefault As Any) As Long  'PRINTER_DEFAULTS
Private Declare PtrSafe Function GetPrinterDriver Lib "winspool.drv" Alias "GetPrinterDriverA" (ByVal hPrinter As LongPtr, ByVal pEnvironment As String, ByVal Level As Long, pDriverInfo As Byte, ByVal cdBuf As Long, pcbNeeded As Long) As Long
Private Declare PtrSafe Function SetPrinterData Lib "winspool.drv" Alias "SetPrinterDataA" (ByVal hPrinter As LongPtr, ByVal pValueName As String, ByVal dwType As Long, pData As Byte, ByVal cbData As Long) As Long
Private Declare PtrSafe Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)

Public Const DM_IN_BUFFER = 8
Public Const DM_OUT_BUFFER = 2

Public Sub SetPrinterProperty(ByVal sPrinterName As String, ByVal iPropertyType As Long)
Dim PrinterName, sPrinter, sDefaultPrinter As String
Dim Pinfo9 As PRINTER_INFO_9
Dim hPrinter, nRet As Long
Dim yDevModeData() As Byte
Dim dm As DEVMODE

'sPrinterName = "Brother MFC-L2700DW series"

'''' STROE THE CURRENT DEFAULT PRINTER
sDefaultPrinter = sPrinterName

'''' USE THE FULL PRINTER ADDRESS TO GET THE ADDRESS AND NAME MINUS THE PORT NAME
PrinterName = Left(sDefaultPrinter, InStr(sDefaultPrinter, " on ") - 1)

'''' OPEN THE PRINTER
nRet = OpenPrinter(PrinterName, hPrinter, ByVal 0&)

'''' GET THE SIZE OF THE CURRENT DEVMODE STRUCTURE
nRet = DocumentProperties(0, hPrinter, PrinterName, 0, 0, 0)
If (nRet < 0) Then MsgBox "Cannot get the size of the DEVMODE structure.": Exit Sub

'''' GET THE CURRENT DEVMODE STRUCTURE
ReDim yDevModeData(nRet + 100) As Byte
nRet = DocumentProperties(0, hPrinter, PrinterName, VarPtr(yDevModeData(0)), 0, DM_OUT_BUFFER)
If (nRet < 0) Then MsgBox "Cannot get the DEVMODE structure.": Exit Sub

'''' COPY THE CURRENT DEVMODE STRUCTURE
Call CopyMemory(dm, yDevModeData(0), Len(dm))

'''' CHANGE THE DEVMODE STRUCTURE TO REQUIRED
dm.dmDuplex = iPropertyType ' 1 = simplex, 2 = duplex

'''' REPLACE THE CURRENT DEVMODE STRUCTURE WITH THE NEWLEY EDITED
Call CopyMemory(yDevModeData(0), dm, Len(dm))

'''' VERIFY THE NEW DEVMODE STRUCTURE
nRet = DocumentProperties(0, hPrinter, PrinterName, VarPtr(yDevModeData(0)), VarPtr(yDevModeData(0)), DM_IN_BUFFER Or DM_OUT_BUFFER)

Pinfo9.pDevmode = VarPtr(yDevModeData(0))

'''' SET THE DEMODE STRUCTURE WITH ANY CHANGES MADE
nRet = SetPrinter(hPrinter, 9, Pinfo9, 0)
If (nRet <= 0) Then MsgBox "Cannot set the DEVMODE structure.": Exit Sub

'''' CLOSE THE PRINTER
nRet = ClosePrinter(hPrinter)

'''' GET THE FULL PRINTER NAME FOR THE CUTE PDF WRITER
sPrinter = GetPrinterFullName("Microsoft Print to PDF")

'''' CHECK TO MAKE SURE THE CUTEPDF WAS FOUND
If sPrinter <> vbNullString Then
'''' THIS FORCES EXCEL TO ACCEPT THE NEW CHANGES THAT HAVE BEEN MADE TO THE PRINTER SETTINGS
    '''' SET THE ACTIVE PRINTER TEMPERARILLY TO THE CUTE PDF WRITER
    Application.ActivePrinter = sPrinter
    '''' SET THE PRINTER BACK TO THE DEFAULY FOLLOW ME.
    Application.ActivePrinter = sDefaultPrinter
End If
End Sub

Public Sub SetDuplex(ByVal sPrinterName As String, iDuplex As Long)
   SetPrinterProperty sPrinterName, iDuplex
End Sub
Public Sub SetSimplex(ByVal sPrinterName As String, iDuplex As Long)
   SetPrinterProperty sPrinterName, iDuplex
End Sub

Public Function GetPrinterFullName(Printer As String) As String

' This function returns the full name of the first printerdevice that matches Printer.
' Full name is like "PDFCreator on Ne01:" for a English Windows and like
' "PDFCreator sur Ne01:" for French.
' Created: Frans Bus, 2015. See http://pixcels.nl/set-activeprinter-excel
' see http://blogs.msdn.com/b/alejacma/archive/2008/04/11/how-to-read-a-registry-key-and-its-values.aspx
' see http://www.experts-exchange.com/Software/Microsoft_Applications/Q_27566782.html

Const HKEY_CURRENT_USER = &H80000001
Dim regobj As Object
Dim aTypes As Variant
Dim aDevices As Variant
Dim vDevice As Variant
Dim sValue As String
Dim v As Variant
Dim sLocaleOn As String

' get locale "on" from current activeprinter
v = Split(Application.ActivePrinter, Space(1))
sLocaleOn = Space(1) & CStr(v(UBound(v) - 1)) & Space(1)

' connect to WMI registry provider on current machine with current user
Set regobj = GetObject("WINMGMTS:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")

' get the Devices from the registry
regobj.EnumValues HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", aDevices, aTypes

' find Printer and create full name
For Each vDevice In aDevices
    ' get port of device
    regobj.GetStringValue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", vDevice, sValue
    ' select device
    If Left(vDevice, Len(Printer)) = Printer Then ' match!
        ' create localized printername
        GetPrinterFullName = vDevice & sLocaleOn & Split(sValue, ",")(1)
        Exit Function
    End If
Next

' at this point no match found
GetPrinterFullName = vbNullString

End Function


Sub TestLayTenMayIn()
    Sheet1.[A1] = GetPrinterFullName("Brother MFC-L2700DW")
End Sub

Sub TestIn2Mat()
Dim UsedRg As Range, Sh As Worksheet
Dim EndR As Long, Pg As Long

SetDuplex GetPrinterFullName("Brother MFC-L2700DW series"), 2
   
For Each Sh In ThisWorkbook.Worksheets
    If Sh.Name <> "Khac" Then
        EndR = Sh.Range("A" & Rows.Count).End(xlUp).Row
        Sh.PageSetup.PrintArea = "$A$1:$F$" & EndR
        Pg = ExecuteExcel4Macro("Get.Document(50)")
        Sh.PrintOut From:=1, To:=Pg, Copies:=1
    End If
Next

SetDuplex GetPrinterFullName("Brother MFC-L2700DW series"), 1

End Sub
 
Lần chỉnh sửa cuối:
Mình cảm ơn bạn đã chia sẻ code. Bạn cho hỏi thêm, là code này dành cho việc in 2 mặt cho file excel mà thay vì trình bày các trang cần in trên 1 sheet (Ví dụ Sheet1: 5 trang cần in) thì chuyển từng trang in cho từng sheet (5 trang là 5 sheet từ Sheet1: 1 trang,Sheet2: 1 trang, Sheet3: 1 trang,Sheet4: 1 trang, Sheet5: 1 trang) . Hay là hỗn hợp kiểu
Sheet1: 2 trang, Sheet2: 1 trang, Sheet3: 2 trang, Sheet4: 1 trang
Bạn có thể nói rõ hơn được không ạ
 
Upvote 0
Code này tôi sưu tầm để trả lời cho 1 bạn nhưng tôi thấy cần đưa thành 1 bài riêng để tiện cho các thành viên tìm kiếm sử dụng cho công việc khi cần. Tôi đã test thành công ở sub TestIn2Mat: Đặt trạng thái in 2 măt, in tất cả các sheet cần in (với mỗi sheet cứ có trang lẻ là in sang tờ mới), trả lại trạng thái in 1 mặt cho máy in.

Thay tên "Brother MFC-L2700DW" bằng tên máy in 2 mặt của bạn.

PHP:
Public Type PRINTER_INFO_9
    pDevmode As Long '''' POINTER TO DEVMODE
End Type

Public Type DEVMODE
    dmDeviceName As String * 32
    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 * 32
    dmUnusedPadding As Integer
    dmBitsPerPel As Integer
    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 Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As Any) As Long
Public Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, buffer As Long, ByVal pbSize As Long, pbSizeNeeded As Long) As Long
Public Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal Command 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, _
                                                                                            ByVal pDevModeOutput As Long, ByVal pDevModeInput As Long, _
                                                                                            ByVal fMode As Long) As Long
Public Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal cbLength As Long)
Public Const DM_IN_BUFFER = 8
Public Const DM_OUT_BUFFER = 2

Public Sub SetPrinterProperty(ByVal sPrinterName As String, ByVal iPropertyType As Long)
Dim PrinterName, sPrinter, sDefaultPrinter As String
Dim Pinfo9 As PRINTER_INFO_9
Dim hPrinter, nRet As Long
Dim yDevModeData() As Byte
Dim dm As DEVMODE

'sPrinterName = "Brother MFC-L2700DW series"

'''' STROE THE CURRENT DEFAULT PRINTER
sDefaultPrinter = sPrinterName

'''' USE THE FULL PRINTER ADDRESS TO GET THE ADDRESS AND NAME MINUS THE PORT NAME
PrinterName = Left(sDefaultPrinter, InStr(sDefaultPrinter, " on ") - 1)

'''' OPEN THE PRINTER
nRet = OpenPrinter(PrinterName, hPrinter, ByVal 0&)

'''' GET THE SIZE OF THE CURRENT DEVMODE STRUCTURE
nRet = DocumentProperties(0, hPrinter, PrinterName, 0, 0, 0)
If (nRet < 0) Then MsgBox "Cannot get the size of the DEVMODE structure.": Exit Sub

'''' GET THE CURRENT DEVMODE STRUCTURE
ReDim yDevModeData(nRet + 100) As Byte
nRet = DocumentProperties(0, hPrinter, PrinterName, VarPtr(yDevModeData(0)), 0, DM_OUT_BUFFER)
If (nRet < 0) Then MsgBox "Cannot get the DEVMODE structure.": Exit Sub

'''' COPY THE CURRENT DEVMODE STRUCTURE
Call CopyMemory(dm, yDevModeData(0), Len(dm))

'''' CHANGE THE DEVMODE STRUCTURE TO REQUIRED
dm.dmDuplex = iPropertyType ' 1 = simplex, 2 = duplex

'''' REPLACE THE CURRENT DEVMODE STRUCTURE WITH THE NEWLEY EDITED
Call CopyMemory(yDevModeData(0), dm, Len(dm))

'''' VERIFY THE NEW DEVMODE STRUCTURE
nRet = DocumentProperties(0, hPrinter, PrinterName, VarPtr(yDevModeData(0)), VarPtr(yDevModeData(0)), DM_IN_BUFFER Or DM_OUT_BUFFER)

Pinfo9.pDevmode = VarPtr(yDevModeData(0))

'''' SET THE DEMODE STRUCTURE WITH ANY CHANGES MADE
nRet = SetPrinter(hPrinter, 9, Pinfo9, 0)
If (nRet <= 0) Then MsgBox "Cannot set the DEVMODE structure.": Exit Sub

'''' CLOSE THE PRINTER
nRet = ClosePrinter(hPrinter)

'''' GET THE FULL PRINTER NAME FOR THE CUTE PDF WRITER
sPrinter = GetPrinterFullName("Microsoft Print to PDF")

'''' CHECK TO MAKE SURE THE CUTEPDF WAS FOUND
If sPrinter <> vbNullString Then
'''' THIS FORCES EXCEL TO ACCEPT THE NEW CHANGES THAT HAVE BEEN MADE TO THE PRINTER SETTINGS
    '''' SET THE ACTIVE PRINTER TEMPERARILLY TO THE CUTE PDF WRITER
    Application.ActivePrinter = sPrinter
    '''' SET THE PRINTER BACK TO THE DEFAULY FOLLOW ME.
    Application.ActivePrinter = sDefaultPrinter
End If
End Sub

Public Sub SetDuplex(ByVal sPrinterName As String, iDuplex As Long)
   SetPrinterProperty sPrinterName, iDuplex
End Sub
Public Sub SetSimplex(ByVal sPrinterName As String, iDuplex As Long)
   SetPrinterProperty sPrinterName, iDuplex
End Sub

Public Function GetPrinterFullName(Printer As String) As String

' This function returns the full name of the first printerdevice that matches Printer.
' Full name is like "PDFCreator on Ne01:" for a English Windows and like
' "PDFCreator sur Ne01:" for French.
' Created: Frans Bus, 2015. See http://pixcels.nl/set-activeprinter-excel
' see http://blogs.msdn.com/b/alejacma/archive/2008/04/11/how-to-read-a-registry-key-and-its-values.aspx
' see http://www.experts-exchange.com/Software/Microsoft_Applications/Q_27566782.html

Const HKEY_CURRENT_USER = &H80000001
Dim regobj As Object
Dim aTypes As Variant
Dim aDevices As Variant
Dim vDevice As Variant
Dim sValue As String
Dim v As Variant
Dim sLocaleOn As String

' get locale "on" from current activeprinter
v = Split(Application.ActivePrinter, Space(1))
sLocaleOn = Space(1) & CStr(v(UBound(v) - 1)) & Space(1)

' connect to WMI registry provider on current machine with current user
Set regobj = GetObject("WINMGMTS:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")

' get the Devices from the registry
regobj.EnumValues HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", aDevices, aTypes

' find Printer and create full name
For Each vDevice In aDevices
    ' get port of device
    regobj.GetStringValue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", vDevice, sValue
    ' select device
    If Left(vDevice, Len(Printer)) = Printer Then ' match!
        ' create localized printername
        GetPrinterFullName = vDevice & sLocaleOn & Split(sValue, ",")(1)
        Exit Function
    End If
Next

' at this point no match found
GetPrinterFullName = vbNullString

End Function


Sub TestLayTenMayIn()
    Sheet1.[A1] = GetPrinterFullName("Brother MFC-L2700DW")
End Sub

Sub TestIn2Mat()
Dim UsedRg As Range, Sh As Worksheet
Dim EndR As Long, Pg As Long

SetDuplex GetPrinterFullName("Brother MFC-L2700DW series"), 2
   
For Each Sh In ThisWorkbook.Worksheets
    If Sh.Name <> "Khac" Then
        EndR = Sh.Range("A" & Rows.Count).End(xlUp).Row
        Sh.PageSetup.PrintArea = "$A$1:$F$" & EndR
        Pg = ExecuteExcel4Macro("Get.Document(50)")
        Sh.PrintOut From:=1, To:=Pg, Copies:=1
    End If
Next

SetDuplex GetPrinterFullName("Brother MFC-L2700DW series"), 1

End Sub
Bây giờ đa số mọi người đã dùng hệ thống 64 bit nên code trên chắc chắn sẽ không chạy. Phải sửa phần code API để tương thích nha bạn
 
Upvote 0
Mình cảm ơn bạn đã chia sẻ code. Bạn cho hỏi thêm, là code này dành cho việc in 2 mặt cho file excel mà thay vì trình bày các trang cần in trên 1 sheet (Ví dụ Sheet1: 5 trang cần in) thì chuyển từng trang in cho từng sheet (5 trang là 5 sheet từ Sheet1: 1 trang,Sheet2: 1 trang, Sheet3: 1 trang,Sheet4: 1 trang, Sheet5: 1 trang) . Hay là hỗn hợp kiểu
Sheet1: 2 trang, Sheet2: 1 trang, Sheet3: 2 trang, Sheet4: 1 trang
Bạn có thể nói rõ hơn được không ạ
Để setting in 2 mặt. In hết sheet này mới chuyện đến sheet khác. Còn chuyện trình bày, định dạng trang in là do bạn.
Bài đã được tự động gộp:

Bây giờ đa số mọi người đã dùng hệ thống 64 bit nên code trên chắc chắn sẽ không chạy. Phải sửa phần code API để tương thích nha bạn
Hình như phần lớn vẫn dùng Win64 bit, Office 32bit chứ bác?
 
Upvote 0
Hình như phần lớn vẫn dùng Win64 bit, Office 32bit chứ bác?
Tại tôi thấy mọi người hay phàn nàn về chuyện code lỗi khi có mấy hàm API, mà đa phần nguyên nhân đều dính đến hệ thống 64 nên tôi nhắc vậy
Nếu có thể được, bạn cứ sửa thành như dưới đây cho chắc
Mã:
Private Declare PtrSafe Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As LongPtr, pDefault As PRINTER_DEFAULTS) As Long
Private Declare PtrSafe Function GetPrinterDriver Lib "winspool.drv" Alias "GetPrinterDriverA" (ByVal hPrinter As LongPtr, ByVal pEnvironment As String, ByVal Level As Long, pDriverInfo As Byte, ByVal cdBuf As Long, pcbNeeded As Long) As Long
Private Declare PtrSafe Function SetPrinterData Lib "winspool.drv" Alias "SetPrinterDataA" (ByVal hPrinter As LongPtr, ByVal pValueName As String, ByVal dwType As Long, pData As Byte, ByVal cbData As Long) As Long
Private Declare PtrSafe Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
 
Upvote 0
Tại tôi thấy mọi người hay phàn nàn về chuyện code lỗi khi có mấy hàm API, mà đa phần nguyên nhân đều dính đến hệ thống 64 nên tôi nhắc vậy
Nếu có thể được, bạn cứ sửa thành như dưới đây cho chắc
Mã:
Private Declare PtrSafe Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As LongPtr, pDefault As PRINTER_DEFAULTS) As Long
Private Declare PtrSafe Function GetPrinterDriver Lib "winspool.drv" Alias "GetPrinterDriverA" (ByVal hPrinter As LongPtr, ByVal pEnvironment As String, ByVal Level As Long, pDriverInfo As Byte, ByVal cdBuf As Long, pcbNeeded As Long) As Long
Private Declare PtrSafe Function SetPrinterData Lib "winspool.drv" Alias "SetPrinterDataA" (ByVal hPrinter As LongPtr, ByVal pValueName As String, ByVal dwType As Long, pData As Byte, ByVal cbData As Long) As Long
Private Declare PtrSafe Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Tks bác!
 
Upvote 0
Máy mình có tới 8 cái máy in, giờ sao biết láy cái máy in nào đang Acti vậy, nếu được bạn chỉ mình với nhé ;)
 
Upvote 0
Máy mình có tới 8 cái máy in, giờ sao biết láy cái máy in nào đang Acti vậy, nếu được bạn chỉ mình với nhé ;)
Dùng code của anh "Bị Phèn" (@befaint) thử xem.
Mã:
Sub GPE()
Dim aPrinters As Object
    Dim i As Long
    With CreateObject("WScript.Network")
        Set aPrinters = .EnumPrinterConnections
        For i = 1 To aPrinters.Count Step 2
          MsgBox aPrinters.Item(i)
        Next
    End With
End Sub
 
Upvote 0
nếu được bạn thêm chức năng láy thêm tên máy in luôn đi, nhiều lúc gặp những người lơ ngơ như mình là pó tay không biết cách sài
 
Upvote 0
Tên máy in mà bạn nhìn thấy rồi lựa nó để in trong hộp thoại Print khi bấm Ctrl+P đấy. Bạn nhìn từ đây rồi gõ vào code
Thông thường phần lớn máy in đã thiết lập sẳn kể cả in 2 mặt. Vì vậy theo tôi không cần thiết ập bằng code. Hoặc nếu thiết lập thì mình sẽ thiết kế một Combobox hoặc Listbox để người dùng chon luôn và ra lệnh in là xong.
 
Upvote 0
Thông thường phần lớn máy in đã thiết lập sẳn kể cả in 2 mặt. Vì vậy theo tôi không cần thiết ập bằng code. Hoặc nếu thiết lập thì mình sẽ thiết kế một Combobox hoặc Listbox để người dùng chon luôn và ra lệnh in là xong.
Prin.png

@Maika8008 mới test không in 2 mặt được máy
TOSHIBA eS850/853Series PCL6 on Ne02:
 
Upvote 0
Thông thường phần lớn máy in đã thiết lập sẳn kể cả in 2 mặt. Vì vậy theo tôi không cần thiết ập bằng code. Hoặc nếu thiết lập thì mình sẽ thiết kế một Combobox hoặc Listbox để người dùng chon luôn và ra lệnh in là xong.
Thế mà có bạn gặp vấn đề khi in 2 mặt 1 lần cho cả sheet gồm vài chục trang in đó bạn. Theo bạn ấy thì chỉ tin được 2 mặt cho 2 trang đầu, còn các trang sau bị chuyển sang 1 mặt. Còn việc gõ tên máy in nào đang dùng để in 2 mặt trong hệ thống của người dùng thì tôi nghĩ họ chỉ cần mở hộp thoại Print xem rồi gõ 1 lần dùng mãi sau đó, không nhất thiết phải cầu kỳ thiết kế một Combobox hoặc Listbox.
 
Upvote 0
Thế mà có bạn gặp vấn đề khi in 2 mặt 1 lần cho cả sheet gồm vài chục trang in đó bạn. Theo bạn ấy thì chỉ tin được 2 mặt cho 2 trang đầu, còn các trang sau bị chuyển sang 1 mặt. Còn việc gõ tên máy in nào đang dùng để in 2 mặt trong hệ thống của người dùng thì tôi nghĩ họ chỉ cần mở hộp thoại Print xem rồi gõ 1 lần dùng mãi sau đó, không nhất thiết phải cầu kỳ thiết kế một Combobox hoặc Listbox.
Vậy mà cứ giả nai.
 
Upvote 0
Thế mà có bạn gặp vấn đề khi in 2 mặt 1 lần cho cả sheet gồm vài chục trang in đó bạn.
Tôi không có máy in để test nên không biết, nhưng tôi đoán là do bạn ấy chọn nhiều sheet in một lượt mới vậy, chứ kiểu in từng sheet thì không bị vậy đâu.
 
Upvote 0
View attachment 239886

@Maika8008 mới test không in 2 mặt được máy
TOSHIBA eS850/853Series PCL6 on Ne02:

Tôi hỏi để chẩn đoán bệnh nhé:
1/ Bạn in thủ công có in được 2 mặt không?
2/ Bạn dùng code này để in thử tại 1 sheet nào đó có 3 trang in thử xem, rồi cho biết có in được không, nếu có lỗi thì chụp hình lỗi gửi lên

Sub In2Mat()

SetDuplex GetPrinterFullName("TOSHIBA eS850/853Series PCL6"), 2
ActiveWindow.SelectedSheets.PrintOut From:=1, To:=2, Copies:=1
End Sub
Bài đã được tự động gộp:

Tôi không có máy in để test nên không biết, nhưng tôi đoán là do bạn ấy chọn nhiều sheet in một lượt mới vậy, chứ kiểu in từng sheet thì không bị vậy đâu.
Tôi cũng nghĩ rằng việc điều khiển máy in chuyển từ trạng thái in 1 mặt -> 2 mặt -> 1 mặt sẽ ích lợi trong nhiều tình huống tự động hóa khâu in ấn. Họ đang tìm code này để dùng cho việc đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi hỏi để chẩn đoán bệnh nhé:
1/ Bạn in thủ công có in được 2 mặt không?
2/ Bạn dùng code này để in thử tại 1 sheet nào đó có 3 trang in thử xem, rồi cho biết có in được không, nếu có lỗi thì chụp hình lỗi gửi lên

Sub In2Mat()

SetDuplex GetPrinterFullName("TOSHIBA eS850/853Series PCL6"), 2
ActiveWindow.SelectedSheets.PrintOut From:=1, To:=2, Copies:=1
End Sub
Bài đã được tự động gộp:


Tôi cũng nghĩ rằng việc điều khiển máy in chuyển từ trạng thái in 1 mặt -> 2 mặt -> 1 mặt sẽ ích lợi trong nhiều tình huống tự động hóa khâu in ấn. Họ đang tìm code này để dùng cho việc đó.
1/ Bạn in thủ công có in được 2 mặt không?
Được nhưng phải check trong Propetiew của máy in
2/ Bạn dùng code này để in thử tại 1 sheet nào đó có 3 trang in thử xem, rồi cho biết có in được không, nếu có lỗi thì chụp hình lỗi gửi lên
mình test 3 Sheet ấy chứ Sheet1 2 tờ, Sheet2 1 tờ, Sheet3 2 tờ.

Sheet nào mà đã chon in 2 mặt thì nó sẽ nhớ không cần check in 2 mặt nữa
thôi không test nữa đâu hao giấy quá bị la chết hihi.
cố gắng Fix đi nhé.
mình đi làm công chuyện đây Bye
 
Upvote 0
1/ Bạn in thủ công có in được 2 mặt không?
Được nhưng phải check trong Propetiew của máy in
2/ Bạn dùng code này để in thử tại 1 sheet nào đó có 3 trang in thử xem, rồi cho biết có in được không, nếu có lỗi thì chụp hình lỗi gửi lên
mình test 3 Sheet ấy chứ Sheet1 2 tờ, Sheet2 1 tờ, Sheet3 2 tờ.

Sheet nào mà đã chon in 2 mặt thì nó sẽ nhớ không cần check in 2 mặt nữa
thôi không test nữa đâu hao giấy quá bị la chết hihi.
cố gắng Fix đi nhé.
mình đi làm công chuyện đây Bye
Vậy sao bài trên bạn nói là
@Maika8008 mới test không in 2 mặt được máy
TOSHIBA eS850/853Series PCL6 on Ne02:
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom