Hi guys, Im looking at writing a print macro for word. the problem is we have an example we cant make head nor tail of.
The Requirements :
Need to be able to vary the copy counts (I.E print a normal letter and then print a plain paper copy)
Need to be able to select a different Printer
Need to be able to vary copy numbers
needs to be able to print duplex
Need to be able to set it so that it prints one Page on letterheaded paper, and the rest on plain paper (using tray selection ID)
Thats what I need from it, but what I need to know is,
1) is there anything in particular that is necessary, i.e. I want to import printers from the windows printers and faxes menu. Do I create a list and link the printers somehow? any tutorials would be greatfully recieved and appreciated.
2) I have extracts of the exampler code if anyone believes it may help us to understand the situation more?!?!? - the problem is because I didnt write the code, I dont know what it is, and my colleagues are telling me that the company we used seemed to have cut and paste macros from over the years together to make the one they have!
I know this is a strange one, and I have looked around for some tutorials but I havent found any that are of any great use and understanding to me.
Am I in well and truely over my head and like the whole Large Hadron Collider theory, just wandering into unchartered territories?
Regards
Jay
Last edited by JayCR; Sep 10th, 2008 at 08:21 AM.
Reason: Because I Can...
Im having an immensely "dull moment", In that post, it says you call it with a certain coding, i.e. the post by lexII said
call it with:
VB Code:
Code:
strNetworkPrinter = GetFullNetworkPrinterName("\\root\Stock Control")
If Len(strNetworkPrinter) > 0 Then ' found the network printer
strCurrentPrinter = Application.ActivePrinter
Application.ActivePrinter = strNetworkPrinter ' change to the network printer ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True ' Print active sheet on chosen printer
Application.ActivePrinter = strCurrentPrinter ' change back to the previously active printer
how do you call that, do you put this, just before the last lot of coding...??
after reviewing the situation I think its going to be easier just to manually install the printers into the application. the way that my example has done it, is by using a PrinternameArray_$ (number) is this the best way to do it? and after looking through all of this coding, I cannot see anything that indicates how this actually points to the printer installed???
Im beginning to feel like im batting my head against a brick wall with this code so I have just quite literally gotten rid of them and am going to do this off a fresh board. my real needs at the moment are trying to create the simple interface. I need to get a drop down box with the printer names in, and link it up so that this selects which printer is actually used to print off from. Can anyone suggest anything for this?
Dim MyPrinters As Printer
'add all installed printers to combo box (if any)
If VB.Printers.Count <= 0 Then
cboPrinters.AddItem "No Printer(s) Installed"
Else
For Each MyPrinters In Printers
cboPrinters.AddItem MyPrinters.DeviceName
Next
End If
cboPrinters.ListIndex = 0
End Sub
look at the last post in the thread, the code he puts in form activate, puts all the printer names into a combobox
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Hi Guys, thanks for the advice, its really starting to help this thing come together. Hack! - I tried your advice on the coding but had no such luck, however after reviewing westconn1's advice, I had a go and managed to get the program to pick up the printers, im wondering can you advise where it says
Code:
PrintCopies = txtCopies.text
Will this actually set the number of copies to whatever number I set? or is there a bit more hocus pocus to this?
also the final Issue I have to address at the moment, is Duplexing... I Have a printer installed on my pc, and also a printer_D (this is the printer with duplex settings and flip on long edge etc set!) Do I need to do this, or can I make my life easier, by deleting these and setting something in the macro to allow duplexing, I have fleeced the following code from a prior macro we were using, and can you tell me wether this should do the job or wether it belongs on this weeks episode of "world's most stupid programming"
Code:
Sub PrintDuplexBooklet()
Dim iDuplex As Long
iDuplex = GetDuplex 'save the current setting
SetDuplex 3 'set for vertical binding
ActiveDocument.PrintOut Background:=False
SetDuplex iDuplex 'restore the original setting
End Sub
Sub DuplexIt()
' iDuplex = GetDuplex 'save the current setting
SetDuplex 2 'set for vertical binding
Selection.HomeKey wdStory
End Sub
Sub UnDuplexIt()
SetDuplex 1 'set for no duplex
End Sub
asfaik there is no provision, in VBA printout method, to set duplex, the printer object in vb can do so, but is not available in VBA
your solution to have 2 printers setup sounds the easiest way to go
if you have the rest of the subs /functions for you code above, ie. setduplex and getduplex, you may be able to use that, but i believe the method they will be using is to change the default properties of the printers in windows (then changeing back), not just the setting for the current document
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
unortunately, that is the only code I have, and after playing around with the code that I posted up there, for all I could get the printer list, it seemed to only print to the PC's default printer, any clues on anything on where to go? im still playing with the rest of the code so will post when my next enquiry most likely will pop up!
i believe i found the setduplex function for the above code, but it kept crashing on my computer, here is a function that i have modified to do what you want, past all the code into a module
Code:
Option Explicit
Private Const CCHDEVICENAME = 32
Private Const CCHFORMNAME = 32
Private Const PRINTER_ACCESS_ADMINISTER = &H4
Private Const PRINTER_ACCESS_USE = &H8
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
Private Const DM_MODIFY = 8
Private Const DM_COPY = 2
Private Const DM_IN_BUFFER = DM_MODIFY
Private Const DM_OUT_BUFFER = DM_COPY
Private Const IDOK = 1
Private Const GMEM_MOVEABLE = &H2
Private Const GMEM_ZEROINIT = &H40
Private Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
Private Const vbNullPtr = 0&
' Add appripriate Constants for what you want to change
Private Const DM_DUPLEX = &H1000&
Private Const DM_ORIENTATION = &H1&
Private Const DM_COPIES = &H100&
Private Const DMPAPER_A4 = 9
Private Const DM_PAPERSIZE = &H2&
' Constants for Duplex
Private Const DMDUP_SIMPLEX = 1
Private Const DMDUP_VERTICAL = 2
Private Const DMDUP_HORIZONTAL = 3
' Constants for Orientation
Private Const DMORIENT_PORTRAIT = 1
Private Const DMORIENT_LANDSCAPE = 2
Private Type ACL
AclRevision As Byte
Sbz1 As Byte
AclSize As Integer
AceCount As Integer
Sbz2 As Integer
End Type
Private Type SECURITY_DESCRIPTOR
Revision As Byte
Sbz1 As Byte
Control As Long
Owner As Long
Group As Long
Sacl As Long ' PACL
Dacl As Long ' PACL
End Type
Private Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As Long
DesiredAccess As Long
End Type
Private Type PRINTER_INFO_2
pServerName As Long ' Pointer to a String
pPrinterName As Long ' Pointer to a String
pShareName As Long ' Pointer to a String
pPortName As Long ' Pointer to a String
pDriverName As Long ' Pointer to a String
pComment As Long ' Pointer to a String
pLocation As Long ' Pointer to a String
pDevMode As Long
pSepFile As Long ' Pointer to a String
pPrintProcessor As Long ' Pointer to a String
pDatatype As Long ' Pointer to a String
pParameters As Long ' Pointer to a String
pSecurityDescriptor As Long
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
Private Type DEVMODE
dmDeviceName(1 To CCHDEVICENAME) As Byte ' 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(1 To CCHFORMNAME) As Byte ' As String * CCHFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Private Declare Function OpenPrinter Lib "winspool.drv" Alias _
"OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, _
pDefault As PRINTER_DEFAULTS) As Long
Private 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
Private 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
Private Declare Function ClosePrinter Lib "winspool.drv" _
(ByVal hPrinter As Long) As Long
Private Declare Function DocumentProperties Lib "winspool.drv" Alias _
"DocumentPropertiesA" (ByVal hwnd As Long, ByVal hPrinter As Long, _
ByVal pDeviceName As String, pDevModeOutput As Any, _
pDevModeInput As Any, ByVal fMode As Long) As Long
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" ( _
hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Public Function Setduplex(myprinter As String, dupval As Long) As Long
Dim hGlobal As Long, hPrinter As Long, dwNeeded As Long
Dim pi2 As PRINTER_INFO_2, i As Integer, pbuf() As Byte
Dim dm As DEVMODE
Dim pd As PRINTER_DEFAULTS
Dim bFlag As Long, lFlag As Long
Dim SD As SECURITY_DESCRIPTOR, SDbuff() As Byte
On Error GoTo ABORT
If dupval < 0 Or dupval > 3 Then MsgBox "invalid duplex value": Exit Function
hGlobal = 0: hPrinter = 0: dwNeeded = 0
pd.pDatatype = "TEXT"
pd.pDevMode = VarPtr(dm)
pd.DesiredAccess = PRINTER_ALL_ACCESS
' Open printer handle (in Windows NT/2000, you need full-access
' because you will eventually use SetPrinter)
bFlag = OpenPrinter(myprinter, hPrinter, pd)
If (bFlag = 0) Or (hPrinter = vbNullPtr) Then GoTo ABORT
' The first GetPrinter() tells you how big the buffer should be in
' order to hold all of PRINTER_INFO_2. Note that this usually returns
' as FALSE, which only means that the buffer (the third parameter) was
' not filled in. You don't want it filled in here.
Call GetPrinter(hPrinter, 2, 0, 0, dwNeeded)
If (dwNeeded = 0) Then GoTo ABORT
' Allocate enough space for PRINTER_INFO_2
ReDim pbuf(dwNeeded)
For i = 0 To dwNeeded
pbuf(i) = 0
Next i
' The second GetPrinter() call fills in all the current settings,
' so all you need to do is modify what you're interested in.
bFlag = GetPrinter(hPrinter, 2, pbuf(0), dwNeeded, dwNeeded)
If bFlag = 0 Then GoTo ABORT
Call CopyMemory(pi2, pbuf(0), Len(pi2))
If pi2.pSecurityDescriptor <> vbNullPtr Then
Call CopyMemory(SD, ByVal pi2.pSecurityDescriptor, Len(SD))
'ReDim SDbuff(Len(SD))
'Call CopyMemory(SD, SDbuff(0), Len(SD))
End If
' Set orientation to Landscape mode and Duplex to Horizontal
' if the driver supports it.
If pi2.pDevMode <> vbNullPtr Then
Call CopyMemory(dm, ByVal pi2.pDevMode, Len(dm))
If dupval = 0 Then ' return current setting only
Setduplex = dm.dmDuplex
ClosePrinter hprinter
Exit Function
End If
'If dm.dmFields And DM_PAPERSIZE Then
If dm.dmFields And DM_DUPLEX Then
' Change the devmode by first setting dmFields to the
' members that will change, using a bitwise Or
dm.dmFields = DM_DUPLEX 'DM_ORIENTATION Or
'dm.dmPaperSize = DMPAPER_A4
' dm.dmOrientation = DMORIENT_LANDSCAPE
dm.dmDuplex = dupval
Call CopyMemory(ByVal pi2.pDevMode, dm, Len(dm))
' Make sure the driver-dependent part of devmode is updated as
' necessary.
lFlag = DocumentProperties(vbNullPtr, hPrinter, _
myprinter, _
ByVal pi2.pDevMode, ByVal pi2.pDevMode, _
DM_IN_BUFFER Or DM_OUT_BUFFER)
If lFlag <> IDOK Then GoTo ABORT
' Update printer information.
' Call CopyMemory(ByVal pi2.pDevMode, dm, Len(dm))
pi2.pSecurityDescriptor = 0
Call CopyMemory(pbuf(0), pi2, Len(pi2))
bFlag = SetPrinter(hPrinter, 2, pbuf(0), 0)
If bFlag = 0 Then GoTo ABORT
Setduplex = True
' The driver supported the change, but it wasn't allowed due to
' some other reason (probably lack of permission).
Else
MsgBox "This printer does not support Duplexing"
End If
Else
' The driver doesn't support changing this.
GoTo ABORT
End If
ABORT:
If (hPrinter <> 0) Then Call ClosePrinter(hPrinter)
' Clean up.
End Function
to set the duplex pass 1 to 3 as dupval, to the setduplex function, should return true or false
to get the existing duplex value pass 0 to the setduplex function, should return 1 to 3 you can then pass this back to the function to return the printer state like
vb Code:
myduplex = Setduplex("HP Color LaserJet 2605", 0)
ret = Setduplex("HP Color LaserJet 2605", 3) 'set duplex on
' print your stuff here, including changing to the correct printer
ret = Setduplex("HP Color LaserJet 2605", myduplex) ' return to original duplex setting
to load all the users printers into a combobox, with port addresses (required for excel)
vb Code:
Dim reg As Variant, oreg As Object, mystr As Variant
Const HKEY_CURRENT_USER = &H80000001
Set oreg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
to set the active printer by selecting the printer from the combobox, in the combobox click event put activeprinter = combobox.text
i have tested the codes above including actually printing
Last edited by westconn1; Sep 14th, 2008 at 04:12 PM.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Thanks Westconn your replies are most certainly a great help!
if I may I have a few questions, and statements between
for reference you asked me to copy the first lot of VBCODE into a module, I have done so and called the module "GetDuplex".
Your second lot of code, am I meant to paste this into the module, or under a particular location in the form? and am I meant to call the module by use of this code, or does it do it automatically?
Secondly, your third lot of code with regards to returning the printer, does this modify the registry in anyway?
Thirdly, you said
"to set the duplex pass 1 to 3 as dupval, to the setduplex function, should return true or false
to get the existing duplex value pass 0 to the setduplex function, should return 1 to 3 you can then pass this back to the function to return the printer state like"
is this a statement of what it does or do I need to set this somewhere within the program? and how do I link these duplex settings to the options, - would I use some code along the lines of...
Code:
IF optDuplexPlainPaper = True THEN
Use your Duplexing Code from the module?
Also one minor problem I have noticed, after selecting the combo box with the printers in (cboSelectPrinterName), I cannot see an Event property, to set the printer as, as Westconn advised in the last post, any clues, or is it best to simply double click and put the following code behind the combo box??
or reference you asked me to copy the first lot of VBCODE into a module, I have done so and called the module "GetDuplex".
Your second lot of code, am I meant to paste this into the module, or under a particular location in the form? and am I meant to call the module by use of this code, or does it do it automatically?
the second should be in the sub or button event you use for printing, or can be in a module and called from the button or whatever
Secondly, your third lot of code with regards to returning the printer, does this modify the registry in anyway?
no just reads the values
1-3 are the valid settings, in vb there is printer object constants to set duplex value, in vba there is not, but you can set your own constants, 1 is single sided, 2 = top join duplex, 3 = side join duplex, it is up to you how you determine if you (or user) want to print duplex, but you should always return the printer to the state it was in previously
IF optDuplexPlainPaper = True THEN
if this is an optionbutton then yes, but consider the printer maybe in duplex mode by default (as mine is), in which case you still need to set duplex, to single side
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
I think its about time I posted the project so that we can all see just what im jabbering about. attatched is the form, exported from MSword. I have set up as much of the coding as I could, however after putting your third lot of code behind the combo box where the user selects the printer, it doesnt seem to work, and im beginning to think im missing something, probably along the lines of a couple of brain cells as well as an eye.
I have set some code behind the duplex option buttons so that if they are sekected they point to the code you showed me. would you care to take a look and then point and laugh at me for where I am going wrong and put me on the right track?
Thanks Again
James
p.s. Westconn, if you live around kent, one day I think I can part with a pint for you, however if you live a little further away it could be a little more difficult!
i think i am a little further away than kent, but maybe i'll take you up on it next summer
i have not looked at your form yet, maybe tomorrow,
you can use the option buttons and combo without code in there events, just read the values from them when you click print
sub cmdprint_click()
activeprinter = combobox.text
if optdup.value then 'set duplex to doublesided
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
i looked at your form in notepad, it does not open for me in word
1. the sub cboselectprinter code should be in form load or activate, so that the printes are loaded when the form starts, replace existing code to fill combobox
2. in that code you should replace the debug.print statement with cboselectprinter.additem, as i said in my original post so that the pritners are put into the combobox
3. no need to hide form before unloading
4. as setting the active printer has no effect outside the current instance of word you can just change it in the combobo change event, no need to change back when finished, no need to set each time you print
5. i have no idea why you have while a < 100 loop it is not needed at all
6. it appears you have 2 comboboxes, cboSelectPrinterModel and cboSelectPrinterName, to do the same job
there is probably more
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
can you tell me how I take the following and ammend it slightly, I have been looking up all sorts of ways to retrieve the current default printer, and none of them seem to work. is there an extra line we can put in to say DefaultPrinter = this value from this string?
Code:
Dim reg As Variant, oreg As Object, mystr As Variant
Const HKEY_CURRENT_USER = &H80000001
Set oreg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
oreg.enumvalues HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", mystr, Arr
For Each reg In mystr
oreg.getstringvalue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", reg, regvalue
'Debug.Print
cboSelectPrinterName.AddItem reg '& " on " & Mid(regvalue, InStr(regvalue, ",") + 1)
Next
you want the windows default printer or the current printer for Word?
which may or may not be the same
if the latter
currentprintername = activeprinter
if the former search on getdefaultprinter API or setdefaultprinter API to change default printeror
or as you are already using scripting, you could put oreg.getstringvalue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\windows", "Device", regvalue
mydefaultprinter = Left(regvalue, InStr(regvalue, ",") - 1)
at the end of your existing code
Last edited by westconn1; Sep 16th, 2008 at 04:35 PM.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
I have to say the API looks too complicated, I have added that code onto the additional, which has realised what my DefaultPrinter is, (that is the value as it is stored in the app!) is there any script as we have for retrieving the value, that I can use to set the value? would something along the lines of writing to the registry the value that is in the "DefaultPrinter" string as the default printer? as this API is starting to look a bit too overcomplicated!
that is an extremely simple API (as far as API go), but note it does not work for win9x
why are you interested in the default printer, you should not need to use /change that, unless you are wanting to do something you have not mentioned before.
the application.activeprinter should do all you want
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
For some reason, it keeps setting the default printer on windows to the printer I am curently using, i.e. my Default is pr1 and if I want Word to use pr2, that then becomes the default windows printer, attached is my newest and most worked on code, by the sounds of it, it shouldnt be doing that then?
Hope this helps, if there is anything else I can do to help diagnose, just let me know, westconn, if its any help to you i will pm you with my email address!
what version of word are you using?
i retested the code i posted, it does not change the windows default printer
i looked at your form and i don't see any code to change the default printer in there, i also do not see any code to print anything at all, or correctly change the printer in word
are you sure this is the code you are using now?
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
the code that is worded out for "controlling the trays" is the printing code, and I am using word XP/2002 at the moment, but it does seem to default the printers... Hope this helps!
Westconn1 and I were talking earlier, and we managed to work out the printer issue, however a tray selection issue is now getting in the way of managing to sort out the duplexing, (I apologise as my thread has jumped from a to b all over) if anyone could help with the tray selection issue, you can find more details at
after much problems and banging my head off a wall, we finally came to an answer with this, so case is nearly closed, however I need to organise the printers in the list and remove some, has anyone any ideas on this? I ahve been advised on putting things into an array, sorting and then putting the array into the combobox, now I know an array is a set of values, but thats as far as my knowledge goes, and I cant grasp how to do this as I have viewed several pages and looked at the MSDN but not got very far, if anyone knows and can show me the light with this, it would be greatly appreciated.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
so how do I sort these in the array, arrays are one thing that I have never been comfortable understanding? So far this is what I have, hope im not too far of the mark!
Code:
Dim reg As Variant, oreg As Object, mystr As Variant
Const HKEY_CURRENT_USER = &H80000001
Set oreg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
oreg.enumvalues HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", mystr, Arr
For Each reg In mystr
oreg.getstringvalue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", reg, regvalue
'Debug.Print
cboSelectPrinterName.AddItem reg '& " on " & Mid(regvalue, InStr(regvalue, ",") + 1)
Next
oreg.getstringvalue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\windows", "Device", regvalue
DefaultPrinter = Left(regvalue, InStr(regvalue, ",") - 1)
cboSelectPrinterName = DefaultPrinter
Dim first, last, i, j As Integer
Dim temp, list As String
first = LBound(mystr)
last = UBound(mystr)
For i = first To last - 1
For j = i + 1 To last
If mystr(i) > mystr(j) Then
temp = mystr(j)
mystr(j) = mystr(i)
mystr(i) = temp
End If
Next j
Next i
For i = 1 To UBound(mystr)
list = list & vbCrLf & mystr(i)
Next
cboSelectPrinterName.Clear
For first = LBound(mystr) To UBound(mystr) - 1
If list <> "" Then
cboselecptintername.AddItem mystr(list)
End If
Next
it is generally better to use a separate sub to sort an array, as they tend to run recursively, search for bubble sort in the vb6 codebank
also you do not specify what criteria you want to sort by
if you just want them sorted alpabetically that is easy enough, but if you want then sorted by some other criteria it can be a bit more complicated
unfortunately forms2 comboboxes do not have a sorted property for the list
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
as I mentioned earlier we have the original printer set up and then the _D counterpart,which has the duplex settings on.I understand that the coding you sent me before to retrieve the printer settings from the registry contains mystr which is the printers in an array, but I dont understand how you are meant to call the list. I need to
1) remove or hide the _D printers from the list as they are just duplicates
2) remove certain items from the list that are present
i.e. the computer contains the following printers installed
Printer1, Printer1_D, Printer2, Printer2_D, printer3, printer4 and printer5
I want the final list to be shown to the users to be the following,
Printer1, Printer2, Printer3 (remove printer4 and printer5 and all _D's)
I have looked up the bubble sorts and various algorithms but none of them explain how they work, or break it down, so I cant understand any of it. if anyone knows of any sites that break it down to simple level that I can use, can you post it for me?
if you only want to use specific printers like that and not get the selection available to the current user, you may as well just specify the printers names in your code, in the order you want them, as whichever way you do it you will have to update the code if the printers are changed
with any type of sort, you go through the list and move one item before or after the next, to set the order
you need to keep going through the list until the items stay in the same order, as it does not all happen in the first pass
quicksort routine is faster (more efficient) than bubble sort, but for a small list bubble sort (simpler code) would be fine
Last edited by westconn1; Sep 26th, 2008 at 08:58 AM.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
with this method where it picks up the printer and we add the exclusions, I want to have some code that says "if the last 2 characters are _D then remove from the list" this means if we add any printers to the network they are automatically detected, we are running about 60 printers on the server and 20 of which are _D but it makes it easier for us....
it does not alter the array, just select not to add items ending in _D
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Dim First As Integer
Dim Last As Integer
Dim i As Integer
Dim j As Integer
Dim Temp As String
Dim List As String
'' 1.
Dim reg As Variant, oreg As Object, Mystr As Variant
Const HKEY_CURRENT_USER = &H80000001
Set oreg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
oreg.enumvalues HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", Mystr, Arr
'Function bubblesort()
cboSelectPrinterName.Clear
First = LBound(Mystr)
Last = UBound(Mystr)
For i = First To Last - 1
For j = i + 1 To Last
If Mystr(i) > Mystr(j) Then
Temp = Mystr(j)
Mystr(j) = Mystr(i)
Mystr(i) = Temp
cboSelectPrinterName.AddItem
End If
Next j
Next i
For i = 1 To UBound(Mystr)
List = List & vbCrLf & Mystr(i)
Next
For Each reg In Mystr
If Not Right(reg, 2) = "_D" Then
oreg.getstringvalue HKEY_CURRENT_USER, "Software\Microsoft\Windows NT\CurrentVersion\Devices", reg, regvalue
cboSelectPrinterName.AddItem reg & " on " & Mid(regvalue, InStr(regvalue, ",") + 1)
End If
Next
This is what code I have managed to put together, it organises the list and puts the values into the combobox, however it has also inserted about 8-10 blank entries in the text box above the first actual printer, have you any ideas on this one?
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
as soon as i disable the following the spaces go and I am left with the printers only, as soon as I re-enable it, the spaces appear, is this statement putting blanks into the array?
Code:
First = LBound(Mystr)
Last = UBound(Mystr)
For i = First To Last - 1
For j = i + 1 To Last
If Mystr(i) > Mystr(j) Then
Temp = Mystr(j)
Mystr(j) = Mystr(i)
Mystr(i) = Temp
cboSelectPrinterName.AddItem
End If
Next j
Next i
For i = 1 To UBound(Mystr)
List = List & vbCrLf & Mystr(i)
Next
you have cboSelectPrinterName.AddItem in your sort, adding blank lines to your combo
just take out that line
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
i am resurrecting this old thread as i have again had need to use duplex from excel
when i originally tested the code as in post #11, it was working fine, but after several reports that the code did not work i did not follow up on the matter at that time
i assume now that when i was testing, the printer i was testing with, was set as the default printer
the code does work with the default printer, but not with any other printer
the below code changes the windows default printer to the desired printer, changes the duplex setting, prints then changes all back
Code:
Sub duplexxxx(pr As String, dup As Long)
Dim pn As String
pn = Left(pr, InStr(pr, " on") - 1)
myprinter = ActivePrinter
defprint = getdef
Ret = SetDefaultPrinter(pn)
myduplex = setduplex(pn, 0) '("HP Color LaserJet 2605", 0)
Ret = setduplex(pn, dup) '("HP Color LaserJet 2605", 3) 'set duplex on
' I decided to remove the msgbox from the module and instead carry it to here, for user remedy
If Not Ret Then MsgBox "Selected printer " & pr & " does not support duplex": GoTo revert
' MsgBox setduplex(pn, 0)
' MsgBox getdef & vbNewLine & ActivePrinter
' print your stuff here, including changing to the correct printer
' ActivePrinter = pr ' DO NOT do this here
DoEvents
ActiveSheet.PrintOut
Ret = setduplex(pn, CLng(myduplex)) '("HP Color LaserJet 2605", myduplex) ' return to original duplex setting
revert:
Ret = SetDefaultPrinter(defprint)
ActivePrinter = myprinter
End Sub
the setdefaultprinter and getdefaultprinter API functions should be added to the module, with all the other API functions
getdefaultprinter needs a function something like
Code:
Function getdef() As String
Dim DefPrinter As String, sLen As Long, hResult As Long
DefPrinter = Space$(255)
sLen = 255
hResult = GetDefaultPrinter(ByVal DefPrinter, sLen)
If hResult <> 0 Then getdef = Left(DefPrinter, sLen - 1)
End Function
also in the module
setdefaultprinter can be called directly as above, but may need its declare to be public
i always did wonder why the code i had tested did not work for others
i hope this might help others trawling this problem
Last edited by westconn1; Mar 17th, 2016 at 06:38 AM.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete