I'm working on some invoice software. So far, I managed to create an excel file (XLSX) with all the info I need (customer info, VAT, pricing etc.)
Now, I want to save this file to PDF so that it can be mailed directly to the customer. Seems kinda hard in Java. To make it easier, I just want to print my source file using the Windows Printing Dialog, and then select a PDF printer.
This little piece of code works, but it starts the printing job immediately using the default printer, without showing any dialog whatsoever. Not what I want.
desktop.print(new File("Docfile.pdf"));
This piece of code displays the printing dialog, but it's not clear to me (looking at the documentation) how I can tell a PrintJob to print a File or FileInputStream...
PrinterJob pj = PrinterJob.getPrinterJob();
pj.print();
Either the first code should display the dialog box, or the second one should give me the ability to select a file. Can't seem to fix it. Anyone got any ideas?
Start by taking a look at the Printing Trail and in particular Using Print Setup Dialogs
From the linked tutorials....
PrinterJob pj = PrinterJob.getPrinterJob();
...
if (pj.printDialog()) {
try {pj.print();}
catch (PrinterException exc) {
System.out.println(exc);
}
}
...
Related
I have a Java program that is built, and is running as a standalone .Jar file. The last build was in start November, and it, along with the previous builds, have been running smoothly.
The function that has stopped working, is where the user wishes to print a receipt, and the program used to show a "Select printer" dialog screen.
But as of today, when the button that runs this function is clicked, nothing happens. The button click effects runs as they should, so the click is registered, but nothing else happens.
I have tried running the .jar file on both my own, and the users computer with same negative result.
However, when i run the project in IntelliJ, and click the button, everything works as it should, with no exceptions or warinings anywhere. I then tried rebuilding it using this very same code. But again, as a separate .jar file, nothing happens. The user, used the very same function as intended just 2 days ago, with the same .jar file that is not working now.
Edit: Opening the jar file in the commandwindow gives a NullPointerException at the line mentioned below.
A remote debug gives this explanation of the object beleived to cause the exception:
JavaFX PrinterJob Printer Microsoft Print to PDF
Collation = UNCOLLATED
Copies = 1
Sides = ONE_SIDED
JobName = JavaFX Print Job
Page ranges = null
Print color = COLOR
Print quality = NORMAL
Print resolution = Feed res=600dpi. Cross Feed res=600dpi.
Paper source = Paper source : Automatic
Page layout = Paper=Paper: A4 size=210.0x297.0 MM Orient=PORTRAIT leftMargin=54.0 rightMargin=54.0 topMargin=54.0 bottomMargin=54.0
Job Status = NOT_STARTED
public class PrintPage {
public void printSetup(Node node, PageOrientation or)
//The class where it prompts for the printer to be used.
{
Stage stage = new Stage();
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
//Line below gives NullPointerException at the job.showPrintDialog(stage) item
if (job.showPrintDialog(stage)) print(job, node, or);
}
stage.close();
}
The errorstack leads from the line above to this part in the javafx PrinterJob class.
public synchronized boolean showPrintDialog(Window owner) {
// TBD handle owner
if (!isJobNew()) {
return false;
} else {
//This line is the next in the stack
return jobImpl.showPrintDialog(owner);
}
}
which leads to an error in:
com.sun.prism.j2d.print.J2DPrinterJob.showPrintDialog(J2DPrinterJob.java:161)
The only null item i see is the Page Ranges, which i can't seem to set.
How do I open up a print dialog box where you select your printer, page details, etc to print A SPECIFIED DOCUMENT OR JTEXTPANE?
Please help!
note: getDesktop().print gives me an error about printer setup, how to open the native print dialog?
Check out Lesson: Printing in Java tutorials, Using Print Setup Dialogs in particular. PrinterJob.printDialog() should do the trick.
An application displays a print dialog when the user presses a button related to the print command, or chooses an item from the print menu. To display this dialog, call the printDialog method of the PrinterJob class:
PrinterJob pj = PrinterJob.getPrinterJob();
//...
if (pj.printDialog()) {
try {pj.print();}
catch (PrinterException exc) {
System.out.println(exc);
}
}
//...
Reference:
Using Print Setup Dialogs
Lesson: Printing
I have the following code that shows a native print dialog in my java application.
PrinterJob job = PrinterJob.getPrinterJob();
PrintRequestAttributeSet atts = new HashPrintRequestAttributeSet();
atts.add(DialogTypeSelection.NATIVE);
if (job.printDialog(atts))
{
PrintService newlyUsedService = job.getPrintService();
DocPrintJob docJob = newlyUsedService.createPrintJob();
// print the passed javax.print.SimpleDoc object.
docJob.print(simpleDoc, atts);
}
This code works fine when a printer is selected and the Print button is clicked, but it does not work when the user selects any option from the “PDF” menu at the bottom left. The getPrintService method returns the last selected printer (Lillith from the screenshot) when one of the options in the "PDF" menu are selected.
Could anyone suggest what should be done to detect when “Save as PDF…” was selected in the print dialog and respond accordingly.
Have you tried adding a Print Job Listener? Just read up on it now, I hope it will be of some help:
Print Job Listener
From within Java, I am opening an Excel file with the default file handler (MS Excel, in this case :-) ) using the method described in this stackoverflow question:
Desktop dt = Desktop.getDesktop();
dt.open(new File(filename));
However, the Excel program doesn't get the focus. Is there any easy way to do so?
Edit: There is a related stackoverflow question for C#, but I didn't find any similar Java method.
Edit 2: I've did some simple tests, and discovered that Excel starts and gets the focus whenever no instance of Excel is running. When Excel is already open en NOT minimized, the application doesn't get the focus. If instead the Excel Windows was minimized, the above code will trigger a maximization of the window and Excel getting the focus (or vice versa :-) ).
If you only care about Windows (implied in the question), you can change the way you invoke Excel: use "cmd start...".
I have been using this piece of code to launch Windows applications for some time now. Works every time. It relies on the file association in Windows to find the application. The launched application becomes the focused window on the desktop.
In your case, Excel should be associated with .xls, .csv and other typical extensions. If it is, Windows will launch Excel, passing your file to it.
Usage:
MyUtilClass.startApplication( "c:\\mydir\\myfile.csv", "my window title" );
file is the full path to the input file for Excel and title is the window title (the application may or may not take it - Excel changes the window title).
public static void startApplication( String file, String title )
{
try
{
Runtime.getRuntime().exec( new String[] { "cmd", "/c", "start", title, file } );
}
catch( Exception e )
{
System.out.println( e.getMessage() );
}
}
From a scala-program, which runs in the JVM too, I can open an application, and that get's the focus by default. (Tested with xUbuntu, which is a kind of Linux).
import java.awt.Desktop
val dt = Desktop.getDesktop ();
dt.open (new java.io.File ("euler166.svg"));
I can't say, whether this is specific for Linux, or maybe something else - however starting Inkscape in my example, excel in yours, may take a few seconds, while the user impatiently clicks in the javaprogram again, thereby claiming the cursor back. Did you check for that?
You could then change to the last application, at least on Linux and Windows with ALT-Tab aka Meta-Tab (again shown in scala code, which you can easily transform to javacode, I'm sure):
import java.awt.Robot
import java.awt.event._
val rob = new Robot ()
rob.keyPress (KeyEvent.VK_META)
rob.keyPress (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_META)
but unfortunately the unknown source off more trouble, also known as user, might do nothing, so switching would be the false thing to do. Maybe with a thread, which checks for a certain amount of time, whether the java-program has the focus, but it keeps a form of roulette, in an interactional environment, because the user may have a fast or slow machine, or change to a third application meanwhile, and so on. Maybe a hint before triggering the new app is the best you can do?
I'm printing a complicated swing application UI to a physical printer via an Airport. I've got Mac & windows machines both printing to the same printer. Printing from the Mac looks great. Printing from windows looks far from great - everything is very pixelated, including fonts and graph lines.
Some digging around reveals that the available PrintServices are different for the different platforms.
DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
PrintServiceLookup.lookupPrintServices(flavor, attrs);
When executed from the mac, the above returns a single-element array. From windows, it returns an empty array. This leads me to believe that windows is sending a 72 DPI image to the printer, instead of postscript data.
Is this a difference in the mac & windows JVM implementations? Is there any workaround to get printing on Windows working? I realize I could generate my own 350dpi rasterized image and send that to the printer, but these things go into the hundreds of pages, I really would like to avoid that route if possible.
Think I got an answer: The java.awt.printerjob system property was set to sun.awt.windows.WPrinterJob. Apparently this is a handy PrinterJob subclass if you like blocky pixelated output on your printer. Instead, I get an instance of sun.print.PSPrinterJob if it's available, like so:
PrinterJob printerJob = null;
try {
if (System.getProperty("java.awt.printerjob").equals("sun.awt.windows.WPrinterJob")) {
// WPrinterJob sends crappy GIF images to the printer, and everything looks all blocky
// try to get an instance of a PSPrinterJob instead
printerJob = (PrinterJob) Class.forName("sun.print.PSPrinterJob").newInstance();
}
} catch (Throwable e1) {
log.log(Level.SEVERE, "Could not instaniate sun.print.PSPrinterJob", e1);
}
if (printerJob == null) {
printerJob = PrinterJob.getPrinterJob();
}