Hello, it is possible to use the Printer object to save PDF files with the Microsoft Print to PDF driver and without user interaction.
HTH
Printable View
Hello, it is possible to use the Printer object to save PDF files with the Microsoft Print to PDF driver and without user interaction.
HTH
What is the purpose or principle of mReplaceAPI?
easy understand...Quote:
Print to specific PDF file name
Assumes Windows 10 with the optional Microsoft Print to PDF driver installed. This is normally the default unless the user has removed it via Windows Features.
Bare bones example. Note that for the most part printing must be done via API calls to avoid raising the driver's file picker dialog
Yes, that was all that the problem was. thanks, Edwardo. your program works great.
Add'l question....
is there a way to autofill the Windows dialog the "Microsoft Print to PDF" presents to the user, and allow the dialog to remain operational? One of the issues that users have is that the windows dialog initially shows with no filename, and users get error if they click either 'Save' or 'Cancel' without properly entering a valid filename. Yes, the users should pay closer attention to their entry and random clicking, but a preventative solution would be to autofill a default FileName, while still allowing the user to use the windows dialog to change directory selection or change the filename if desired.
No, but easy to add that:
Code:Private Sub Command1_Click()
Dim strCurrentPrn As String
strCurrentPrn = Printer.DeviceName
If Not SelectPrinter("Microsoft Print to PDF") Then
MsgBox "Can't save PDF, 'Microsoft Print to PDF' driver not present", vbCritical
Exit Sub
End If
PrinterFilePath = "D:\test.pdf"
Printer.Print "AAA"
Printer.FontSize = 34
Printer.Print "BBB"
Printer.DrawWidth = 10
Printer.Circle (1000, 1000), 500, vbRed
Printer.EndDoc
PrinterFilePath = ""
SelectPrinter strCurrentPrn
End Sub
Could I ask what the difference is between your work and this one vbImg2Pdf
I don't think the two projects have much in common.
vbimg2pdf:
You can do that also with this project, but with this project you can print anything, not just images.Quote:
Convert jpeg/png images to multi-page pdf file
And the most important feature is that you do it with the Printer object.
On the other and, it seems that that project splits automatically the images into several PDF pages. I don't think the Printer object will do that automatically.
So, basically, they are two completely different projects, with different goals.
Also, another key difference is that this method requires the "Microsoft Print to PDF" driver installed.
yes, have tested your code, very impressive
Code:Printer.NewPage
Printer.PaintPicture LoadPicture("c:\1.jpg"), 0, 0
Hi, someone can guide me to use this apis in order to save a datareport to PDF, using a pdf printer (Microsoft print ot pdf)?
i tried everything without success :-(
Thanks in advance
Hi, thanks for answering.
I found "why it wasn't working", i used your code from the first post, but it never filled the pdf file, and today... looking quietly my code, i found that i was setting the "microsoft printer to pdf " with a loop and "set printer = x", BUT not with the API that sets the default printer.
Once i selected the Microsoft Printer to PDF as "default", not only with the set printer... it worked like a charm.
Thanks a lot for your code !
Me too! Just used this today and works great. Thanks Eduardo!
Your code is so clever! It is really useful to me.
Thank you
It was working fine until today.
I found I need to start the exe with admin privileges in in order to work again (windows 10),
Any chance to make it work again without using as admin the app?
Thanks !
Just tested:
I downloaded the sample project from the first post.
Compiled the exe.
Ran it and clicked the button.
The file d:\test.pdf was created as expected.
Windows 11 22H2 with up to date automatic updates installed.
My project runs fine in the IDE and produces a perfect PDF report.
However when I try to compile I get the following error.
---------------------------
Microsoft Visual Basic
---------------------------
Programmatic ID string too long 'TracsDashboard.cAutoRestoreFunctionOnExit'. The Programmatic ID must be 39 characters or less.
---------------------------
OK Help
---------------------------
Oh..
You are right, I tried the sample and worked fine...
I have to find then why when I use the printer.enddoc statement, my programs ends.
An API conflict ? I must recheck then everything :-(
Thanks !
Checked, they are fine, i will start a new project adding slowly all the .bas files.
I think the new vbflexgrid from Krool it's making some kind of problem, i deleted (in a copy) the uctabmdi files, the sendmail and some other with apis ...
i checked that no public apis exists inside the project...
Weird.. i have to spend more time finding where this problem is :_(
Just copy the files mReplaceAPI.bas and AutoRestoreFunctionOnExit.cls as they are here and it should work fine, since the APIs are all there and are declared Private.
If it still crashes then it must be something else.
Hi, thanks again, i found what it was!
I used the code to save a datareport to a pdf from a Mdi form. Everything was ok.
But i had to change the form from Mdi child to one normal, but... modal...
And.. i was still launching the datareport whitout being modal .... , (i can launch a normal form / datareport from a modal form, without doing it modal too) the strange thing is no error was sent anywhere... but i found it finally.. working like a charm again!
Thanks!
Hi again :-(
I need a little help, i don't know what else i have to do.
Your example works always, it's perfect.
I want to print a datareport to pdf, and i use your code.
My program:
In IDE it works 99% of time.
In compiled exe, it only works 1% time.
Normally it hangs and closes everything.
I'm doing:
1.- creating a recordset
2.- using a datareport without the .show instruction (if i use the .show, it works fine and i can see the datareport fine)
Then, instead of showing the datareport, i use:
Code:PrinterFilePath = "c:\temp\example.pdf"
Informe_ECI.PrintReport
Printer.EndDoc
PrinterFilePath = ""
When it arrives to printerfilepath="" and start it, is when it usually hangs.... (my program closes, without error)
Tested in windows 10 (my development machine is win 10 too), and windows 11...
I'm pretty sure it's a problem from the datareport part, but...
Any idea ?
Thanks in advance !
Edit: !!
Solved compiling the program as P-Code
Thanks!
As the title says, this code is for saving PDF files with "VB's Printer object".
DataReport <> Printer object.
Anyway the code should work also transparently for any other component that used the StartDocA API.
But, you shouldn't mix DataReport commands with Printer.EndDoc, they are different objects/components.
For working with other components, you need to ensure that before starting a print job, the component will use the "Microsoft Print to PDF" driver for printing.
That's done for the Printer object in the sample code in the SelectPrinter procedure, but that will only select the current printer for the Printer object, not for other components.
I don't remember how to select the current printer in DataReport (look on internet, or in this forum, or ask in the general forum, or maybe someone seeing post it here).
And at the end, let the component (DataReport in this case) do the "EndDoc" for itself, don't call Printer.EndDoc because it has nothing to do.
Hi! Did you really get this working? I mean, it works for me, however when I open the PDF file, I get: Acrobat reader could not open test.pdf because it is either not a supported file or because the file has been damaged (for example, it was sent as an email attachment and wast correctly decoded)
Any clues, please?
Hey! Thank you for responding. I did have it set to "Microsoft Print to PDF", and somehow, 40 minutes ago, I changed the position of the DataReport.Refresh before FilePath, and for some reason, it worked... go figure!!!
Like another user said, without P-CODE, the app and sometimes VB6 as I was testing, would just close unexpectedly. I wish I knew what is causing that, because I never used P-CODE (don't even know what it is) and I am afraid that using PCODE, will create other issues... But I honestly have no idea what to look for, I am not that good with VB6.
By the way, amazing code, it really solved my immediate problem, as I could not for the life of me, find Crystal Reports to even try doing the report I needed. Unfortunately, I cant code the report using your example, but I will test it a little more and hopefully it wont be an issue using PCODE.
Really great code! Are you Brazilian? They used to code VB6 like no one else.
Thank you again, and if you ever, ever figure out what makes the code not work without P-CODE (or if it does not matter), please let me know!
Who talked about PCODE? I don't think the issue has anything to do with PCODE or not PCODE.
I am argentinian.
The crash will happen if you close the program without resetting the API hook to the original state.
Set PrinterFilePath = "" inmediately after the printing operation, and don't end the program before doing that.
HI, i have it solved. i'm doing:
First Dim/Declare this:
Code:Dim strCurrentPrn As String
Dim p As Printer
Private Declare Function SetDefaultPrinter Lib "winspool.drv" Alias "SetDefaultPrinterA" (ByVal pszPrinter As String) As Long
Create this sub
Code:Private Sub Pausa(Tiempo As Byte)
Dim TiempoPausa, inicio, Final, TiempoTotal
TiempoPausa = Tiempo
inicio = Timer
Do While Timer < inicio + TiempoPausa
DoEvents
Loop
End Sub
Then, when you want to print:
Code:
strCurrentPrn = Printer.DeviceName ' Save Actual Printer
'Search if we have installed the PDF printer
For Each p In Printers
If p.DeviceName = "Microsoft Print to PDF" Then
SetDefaultPrinter p.DeviceName
Set Printer = p
GoTo ItsOk
End If
Next p
MsgBox "No PDF Printer found", vbCritical, "Error!!"
Exit Sub
ItsOk:
PrinterFilePath = "C:\TEMP\" & Filename
'Print Datareport
'##########
Datareport_Name.PrintReport False, rptRangeAllPages
'Do a Pause (Important!!!) (I found that if you create the PDF in a local hard drive, it works better than in a network folder)
'##############################################################################
Pausa 1
PrinterFilePath = ""
'returning Printer
'##########
For Each p In Printers
If p.DeviceName = strCurrentPrn Then
Set Printer = p
SetDefaultPrinter p.DeviceName
Exit For
End If
Next
Unload Informe <----- this is the Datareport's name
' closing recordset and connection to mysql
If Rst.State = 1 Then
Rst.Close
End If
If Cnx.State = 1 Then
Cnx.Close
End If
Set Rst = Nothing
Set Cnx = Nothing
It's not working for me; it creates a 0-byte pdf in the specified directory and then locks up (not oh exit, after clicking the button). (To be clear, yes I am talking about VB6, not tB; in tB, it locates and writes the memory at lPtr, but it doesn't work to replace the function; want to get it working in VB6 before pursuing it)
I'm talking about Vb6 too.
Did you do everything? i mean, used the "pausa" sub.
I had this problem too, it was solved with the pausa sub, try to put 2 or 3 seconds (just to try)
you can change Registry for pdf printer port to D:\002.PDF OR E:\ABC.PDF
If you modify the exported PDF path every time you print it, you can realize continuous numbering. Save to any file name and path.
You don't need any hook API, and you don't need to write any code.
Just change the port of the printer from USB,LPT to file name, as simple as that.
Code:Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports]
"D:\\output.pdf"=""
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\Microsoft Print to PDF]
"ChangeID"=dword:0b79c556
"StatusExt"=dword:00000000
"Status"=dword:00000180
"Name"="Microsoft Print to PDF"
"Port"="D:\\output.pdf"
use hook api,you can try how to hook word.exe open file and savefile ,so it can be load virtual file from memroy without disk.
Virtual file, let windows media player ocX load MP3 from file, and change it into memory variable.
Can you do something similar? In any case, it is really convenient to use various HOOK functions in VB6 ide.
Printer.Circle (1000, 1000), 500, vbRed
Can this draw polygons, ellipses, rounded rectangles, and support a variety of graphic line shapes?
How to modify this code to run on 64 bits. Above VBA, twinbasic
Printer object cannot write elements by coor.
This is of no use, and a restart of the print service may be required after the modification.
Attachment 193886
Hi!
Returning to this thread.
Like some user said before, if i compile the project with P-CODE, everything works fine, but for some reason i need now to compile to native code... and it crashes now.
The code is simple:
Just when executing Printerfilepath = "", program closes. in IDE it works fine, but no compiled.Code:PrinterFilePath = "S:\Clientes\" & temp_Nombre_del_fichero
FPrincipal.InfoI.Caption = "Imprimiendo Datareport"
FPrincipal.InfoI.Refresh
Informe_ECI.PrintReport False, rptRangeAllPages
FPrincipal.InfoI.Caption = "Devolviendo API"
FPrincipal.InfoI.Refresh
PrinterFilePath = ""
Any idea about what to do? (my knowledge with APis is so limited :-( )
I just tested the sample project that is in the first post compiled to native code and it worked perfectly.
I think you are right, sorry!, i used a lot of "msgbox" to see where is really crashing, and it's just after:
Informe_ECI.PrintReport False, rptRangeAllPages
it's not arriving to printerfilepath = ""....
I hate the datareports..., let's see why they don't work if i change the compilation mode...
when vba call word.print,how to change pdf save path?
on vb6 use “word.application",document.print ,how to change for pdf savepath?
[QUOTE=wtusvi;5667319]This is of no use, and a restart of the print service may be required after the modification.
maybe can refresh Registry by windows api?
It's not necessary. twinBASIC supports setting the path natively, just set Printer.OutputFile.
Edit: But I did write basic 64bit API hooking code based on the functions in this thread... I changed to hijacking the MsgBox but the code has the same generic ReplaceFunction and RestoreFunction...
https://gist.github.com/fafalone/635...8484e516f5f205
Solved my problem.
It was the datareport.
Changed all the datareports to PRINT (yes... a lot of work, but now everything works fine)
Thanks!