Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Printing to .pdf file without dialogue

Status
Not open for further replies.

AndrewMozley

Programmer
Oct 15, 2005
621
GB
I feel that this must have been asked many times before! I have an application which I have installed at a few sites, and I want to allow printing to .pdf files.

At present I am using PDF Creator (which is free) and this appears as a printer which the user may select. At run-time the user is invited to select a destination folder and file name, and this works fine.

I would like however to be able to complete the whole task within the application: I will have created the .dbf with the results that I wish to print, decided what .frx/.frt layout I wish to use, and also determined the name and folder of the output .pdf file that I want to create. So I would like to generate the file without requiring further input from the user.

Is it possible to do this? I had looked at XFRX which may have the facilities, but although I could afford $249, I get the impression that I am not allowed to distribute the XFRX application to my customers - so it could only be for my in-house use.

If anyone has produced .pdf files as described, and can point me towards a step-by step guide to installing and using a suitable product (free would be nice!) I would be grateful.

Thanks. Andrew
 
This is what I use for FoxyViewer and it works like a charm:

**
SET PROCEDURE TO LOCFILE("FoxyPreviewer.App") ADDITIVE
LOCAL loReport as "PreviewHelper" OF "FoxyPreviewer.App"
loReport = CREATEOBJECT("PreviewHelper")
WITH loReport as ReportHelper
.AddReport("Name_Of_Your_FRX_FRT_File", "NODIALOG")
.cDestFile = "YourPDF_Name.pdf" &&' Use to create an output without previewing - The output report is called YourPDF_Name.pdf
.RunReport()
ENDWITH

I hope that helps too.

Ciao,
FOXUP
 
IMHO XFRX is the way to go. It has endless options, one of them which I find very useful is to chain more than one report into the same pdf.
This can also be done entirely in memory and exported to a physical printer. This way my users can use the stapling function of their printer to automatically do just that - staple together documents which belongs to the same print-out.
And of course it can also export to many other sorts of documents, XLS, DOC etc WITHOUT Office being installed.
No I'm not associated with but I've used XFRX for maybe 10 years now and I'm very pleased. Support is also excellent!
 
Because it's better to have multiple choices, download PDFCreator version 1.7.3 (not the most recent version) from
I just downloaded version 1.7.3, and successfully tested this demo :

P.S. PDFCreator has an autosave mode
Code:
DECLARE Sleep IN kernel32 INTEGER
LOCAL lcRepName,lcFileName,lcFolder,oPDFC,lcOldDefaPrint,DefaultPrinter,laf[1],lnCount

CREATE CURSOR cc (ii I)
APPEND BLANK
GO top
lcFolder = ADDBS(JUSTPATH(SYS(16)))
lcRepName = m.lcFolder  + "cc.frx"
CREATE REPORT (m.lcRepName) FROM cc
lcFileName = "cc.pdf"

IF ADIR(laf,m.lcFolder+m.lcFileName) > 0
	ERASE (m.lcFolder+m.lcFileName)
	IF ADIR(laf,m.lcFolder+m.lcFileName) > 0
		MESSAGEBOX("Can't create " + m.lcFolder+m.lcFileName,16,"Erase the old PDF")
		RETURN
	ENDIF
ENDIF
lcOldDefaPrint = Alltrim(Set('PRINTER', 2))

oPDFC  = CREATEOBJECT("PDFCreator.clsPDFCreator","pdfcreator")
oPDFC.cStart("/NoProcessingAtStartup")
oPDFC.cOption("UseAutosave") = 1
oPDFC.cOption("UseAutosaveDirectory") = 1
oPDFC.cOption("AutosaveFormat") = 0              &&  ; 0 = PDF format
DefaultPrinter = oPDFC.cDefaultprinter
oPDFC.cDefaultprinter = "pdfcreator"
oPDFC.cClearCache
ReadyState = 0
oPDFC.cOption("AutosaveFilename") = m.lcFileName
oPDFC.cOption("AutosaveDirectory") = m.lcFolder
oPDFC.cprinterstop=.F.

SET PRINTER TO NAME (oPDFC.cDefaultprinter) && Fix this 
REPORT FORM (m.lcRepName) NOCONSOLE TO PRINTER 

lnCount = 0
DO WHILE ADIR(laf,m.lcFolder+m.lcFileName) = 0 AND m.lnCount <= 40
    sleep(50)
    lnCount = m.lnCount + 1
ENDDO
oPDFC.cDefaultprinter = DefaultPrinter
oPDFC.cClearCache
RELEASE m.oPDFC

Set Printer To Name (m.lcOldDefaPrint)


Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Thanks very much Wilhelm. I have re-installed PDFCreator 1.73, run your test and it works, creating a file cc.pdf. Most grateful.

Only thing that I noticed is that there is a brief flash on the screen at the time of executing the REPORT FORM instruction. Any idea why that would be happening?

Andrew
 
I guess is the printer spooler.

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Just as a side note since I don't know the advantages of another utility, I've used a modified version of Print2PDF.PRG by Paul James (Life-Cycle Technologies, Inc.) here: github.com/qpjames/Print2PDF

We started with older version 1.5 and I had to tweak it, I especially recall when GhostScript (interface for PostScript output) changed its default path folder naming. The entire process can work in the background with only the user prompts you deem appropriate.

Code:
**************************************************************************************
* GSFind() - Finds the Ghostscript DLL path and adds it to the VFP path
**************************************************************************************
FUNCTION GSFind()

	this.lFoundGS = .F.

	** Check to see if already assigned path
	IF FILE(this.cGSFolder+"gswin64c.exe") OR FILE(this.cGSFolder+"gswin32c.exe")
		this.cGSExeFile = IIF(FILE(this.cGSFolder+"gswin64c.exe"), "gswin64c.exe", "gswin32c.exe")
		this.lFoundGS = .T.

	ENDIF

	* Find the GhostScript executable in order of most likely directories with priority of 64 bit over 32 bit
	IF !this.lFoundGS
		IF this.assignGSPath("C:\PROGRAM FILES\GS\", "64") OR this.assignGSPath("C:\PROGRAM FILES (x86)\GS\", "64") OR this.assignGSPath("C:\GS\", "64") OR ;
			this.assignGSPath("C:\PROGRAM FILES\GS\", "32") OR this.assignGSPath("C:\PROGRAM FILES (x86)\GS\", "32") OR this.assignGSPath("C:\GS\", "32")
			this.lFoundGS = .T.
		ENDIF
	ENDIF

	* If Ghostscript was not found then post an error
	IF !this.lFoundGS
		this.cError = "Could not find GhostScript."+STR(LINENO())
		this.lError = .T.
	ENDIF

	RETURN this.lFoundGS
ENDFUNC


FUNCTION assignGSPath
	LPARAMETERS gspathroot_clp, gs32or64_clp
	LOCAL gsfolders_a[1], gsfolder_n, gsfoldercoll_n, gsfolder_c, gsexefile_c, gsfound_b

	gsfound_b = .F.

	gsfoldercoll_n = ADIR(gsfolders_a, gspathroot_clp+"*.*", "D")
	ASORT(gsfolders_a,1,-1,1,1)  && Sort on filename, entire array, reverse order, ignore case

	FOR gsfolder_n = 1 TO gsfoldercoll_n
		gsfolder_c = ALLTRIM(UPPER(gsfolders_a[gsfolder_n,1]))
		IF "GS" = LEFT(gsfolder_c, 2) and "D" $ gsfolders_a[gsfolder_n, 5]

			this.cGSFolder = gspathroot_clp + ALLTRIM(gsfolder_c)+"\bin\"
			* Below should be:
			* C:\Program Files\gs\gs8.54\lib;C:\Program Files\gs\fonts;C:\Program Files\gs\gs8.54\Resource
			this.cGSFolderPath = SUBSTR(this.cGSFolder,1,LEN(this.cGSFolder)-5)+"\lib;" + ;
										SUBSTR(this.cGSFolder,1,LEN(this.cGSFolder)-5)+"\resource;" + ;
										SUBSTR(this.cGSFolder,1,LEN(this.cGSFolder)-5-LEN(ALLTRIM(gsfolder_c)))+"fonts"
			gsexefile_c = "gswin"+gs32or64_clp+"c.exe"
			IF FILE2( this.cGSFolder + gsexefile_c )
				this.cGSExeFile = gsexefile_c
				gsfound_b = .T.
			ENDIF

			EXIT
		ENDIF
	ENDFOR

RETURN gsfound_b
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top