Print MigraDoc document to specific printer - printing

I've created a MigraDoc/PdfSharp document and now need to send it to a specific printer without any user interaction.
What do I need to use as a Renderer and how do I set the printer path/name to the MigraDocPrintDocument?

MigraDocPrintDocument is the correct class.
// Creates a PrintDocument that simplyfies printing of MigraDoc documents
MigraDocPrintDocument printDocument = new MigraDocPrintDocument();
// Attach the current printer settings
printDocument.PrinterSettings = printerSettings;
We use System.Windows.Forms.PrintDialog() to let the user select the printer (this dialog fills the printerSettings structure).
Use
internal PrinterSettings printerSettings = new PrinterSettings();
for the default printer. Change this structure to print with different settings or on a different printer.
Please note that with PDFsharp 1.31, printing will work with the GDI+ build only (the WPF build will not print the document correctly).

Related

Ghostscript mswinpr2 does not select default setting

I must provide a silent print of PDF to physical printer. I'm using ghostscript but I have a problem: the windows default printer settings are ignored by ghostscript.
For example if I select color to b/w or paper tray in default printer settings these are ignored during the print.
If I let user select the printer with printer dialog, it works, but I need a silent print.
This is my C# Code, it is linked to ghostscript with Ghostscript.NET library
using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dPrinted");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOSAFER");
switches.Add("-dNumCopies=" + nrcopies);
switches.Add("-sDEVICE=mswinpr2");
if (!String.IsNullOrWhiteSpace(printerName))
switches.Add("-sOutputFile=%printer%" + printerName);
switches.Add("-f");
switches.Add(inputFile);
processor.StartProcessing(switches.ToArray(), null);
}
I found this solution, another switch for ghostcript:
switches.Add("-dQueryUser=3");

Zebra Printer - Cut on last page

I've a Zebra ZT610 and I want to print a label, in pdf format, containing multiple pages and then have it cut on the last page. I've tried using the delayed cut mode and sending the ~JK command but I'm using a self written java application to do the invocation of printing. I've also tried to add the string "${^XB}$" into the PDF document before each page break, except the last, and used the pass-through setting in the driver to inhibit the cut command but that seems to not work either as the java print job is rendering such text as an image.
I've tried the official Zebra driver as well as using the NiceLabel zebra driver too in the hope that they may have more "Custom Commands" options in the settings but nothing has yet come to light.
After we had the same issues for several weeks and neither the vendor nor google nor Zebra's own support came up with a FULL working solution, we've worked out the following EASY 5 step solution for this (apparently pretty common) Zebra Cutter issue/problem:
Step 1:
Set Cutter-Mode to Tear-Off in the settings.
This will disable the auto-cutting after every single page.
Step 2: Go to Customer-Commands in the settings dialog (Allows ZPL coding).
Step 3: Set the first drop-down to "DOCUMENT".
Step 4: Set the Start-Section to "TEXT" and paste in
^XA^MMD^XZ^XA^JUS^XZ
MMD enables PAUSE-Mode. The JK command is only available in Pause-Mode and many Zebra printers do not support the much easier command CN (Cut-Now).
JUS saves the setting to the printer.
Step 5: Set the End-Section to "ANALYZED TEXT" and paste in
˜JK˜PS
JK sets the cut command to the end of the document, PS disables the pause mode (and thus starts printing immediately). When everything looks as described above, hit "APPLY" and your Zebra printer will automatically cut after the end of each document you send to it. You just send your PDF using sumatra or whatever you prefer. The cutter handling is now automatically done by the printer settings.
Alternatively, if you want to do this programmaticaly, use the START and END codes at the corresponding positions in your ZPL code instead. Note that ˜CMDs cannot be send in combination with ^CMDs, thats why there's no XA...XZ block to reset any settings (which is not necessary in this scenario as it only affects the print session and PS turns the pause mode back to OFF).
I had similar concern but as the print server was CUPS, I wasn't able to use Windows drivers and utilities (settings dialog). So basically, I did the following:
On the printer, set Cutter mode. This will cut after each printed label.
In my Java code, thanks to Apache PDFBox lib, open the PDF and for each page, render it as a monochrome BufferedImage, get bytes array from it, and get its hex representation.
Write a few ZPL commands to download hex as graphic data, and add the ^XB command before the ^XZ one, in order to prevent a cut here, except for the last page, so that there is a cut only at the end of the document.
Send the generated ZPL code to the printer. In my case, I send it as a raw document through IPP, using application/vnd.cups-raw as mime-type, thanks to the great lib ipp-client-kotlin, but it is also possible to use Java native printing API with bytes.
Below in a snippet of Java code, for demo purpose:
public void printPdfStream(InputStream pdfStream) throws IOException {
try (PDDocument pdDocument = PDDocument.load(pdfStream)) {
PDFRenderer pdfRenderer = new PDFRenderer(pdDocument);
StringBuilder builder = new StringBuilder();
for (int pageIndex = 0; pageIndex < pdDocument.getNumberOfPages(); pageIndex++) {
boolean isLastPage = pageIndex == pdDocument.getNumberOfPages() - 1;
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(pageIndex, 300, ImageType.BINARY);
byte[] data = ((DataBufferByte) bufferedImage.getData().getDataBuffer()).getData();
int length = data.length;
// Invert bytes
for (int i = 0; i < length; i++) {
data[i] ^= 0xFF;
}
builder.append("~DGR:label,").append(length).append(",").append(length / bufferedImage.getHeight())
.append(",").append(Hex.getString(data));
builder.append("^XA");
builder.append("^FO0,0");
builder.append("^XGR:label,1,1");
builder.append("^FS");
if (!isLastPage) {
builder.append("^XB");
}
builder.append("^XZ");
}
IppPrinter ippPrinter = new IppPrinter("ipp://printserver/printers/myprinter");
ippPrinter.printJob(new ByteArrayInputStream(builder.toString().getBytes()),
documentFormat("application/vnd.cups-raw"));
}
}
Important: hex data can (and should) be compressed, as mentioned in ZPL Programming Guide, section Alternative Data Compression Scheme for ~DG and ~DB Commands. Depending on the PDF content, it may drastically reduce the data size (by a factor 10 in my case!).
Note that Zebra's support provides a few more alternatives in order to controller the cutter, but this one worked immediately.
Zebra Automatic Cut - Found another solution.
Create a file with the name: Delayed Cut Settings.txt
Insert the following code: ^XA^MMC,N^XZ
Send it to the printer
After you do the 3 steps above, all the documents you send to the printer will be cut automatically.
(To disable that function send again the 'Delayed Cut Setting.txt' with the following code:^XA^MMD^XZ )
The first document you send to the printer, you need to ADD (just once) the command ^MMC,N before the ^XZ
My EXAMPLE TXT:
^XA
^FX Top section with logo, name and address.
^CF0,60
^FO50,50^GB100,100,100^FS
^FO75,75^FR^GB100,100,100^FS
^FO93,93^GB40,40,40^FS
^FO220,50^FDIntershipping, Inc.^FS
^CF0,30
^FO220,115^FD1000 Shipping Lane^FS
^FO220,155^FDShelbyville TN 38102^FS
^FO220,195^FDUnited States (USA)^FS
^FO50,250^GB700,3,3^FS
^FX Second section with recipient address and permit information.
^CFA,30
^FO50,300^FDJohn Doe^FS
^FO50,340^FD100 Main Street^FS
^FO50,380^FDSpringfield TN 39021^FS
^FO50,420^FDUnited States (USA)^FS
^CFA,15
^FO600,300^GB150,150,3^FS
^FO638,340^FDPermit^FS
^FO638,390^FD123456^FS
^FO50,500^GB700,3,3^FS
^FX Third section with bar code.
^BY5,2,270
^FO100,550^BC^FD12345678^FS
^FX Fourth section (the two boxes on the bottom).
^FO50,900^GB700,250,3^FS
^FO400,900^GB3,250,3^FS
^CF0,40
^FO100,960^FDCtr. X34B-1^FS
^FO100,1010^FDREF1 F00B47^FS
^FO100,1060^FDREF2 BL4H8^FS
^CF0,190
^FO470,955^FDCA^FS
^MMC,N
^XZ

are there some way to print by xps printer without show the save dialog?

I'm trying to print by XPS PRINTER without the save dialog.
I'm using the Printer Object on VB6.
Any Idea?
It's not possible to control the XPS Document Writer file name from VB6, but it is possible using a third party product named Win2PDF. To set the XPS file name in Win2PDF, you use the SaveSetting method to save the file name to the registry as in:
SaveSetting "Dane Prairie Systems", "Win2PDF", "PDFFileName", "c:\test\test.xps"
After calling SaveSetting with the key set to "PDFFileName", you print to the Win2PDF printer using the VB6 printer object to create the XPS file.

Using printer name Adobe PDF

I have looked everywhere for this solution. The code below allows me to print to the printer, Adobe PDF, but what I want to do is automate the file name save as screen with a generic name and in a specific folder. For example, the file would be saved to C:\temp\tmpResize.pdf and I am having problems there.
var params = this.getPrintParams();
params.interactive=params.constants.interactionLevel.silent;
params.pageHandling=params.constants.handling.none;
params.fileName = "/c/temp/tmpResize.pdf";
params.printerName="Adobe PDF"
this.print(params);
Thanks for your help.

Way to default the name of the generated XPS file?

If a user prints a report, and they happen to be using the Microsoft XPS printer, i would like the default the filename to something meaningful.
i would have thought that the XPS printer would take the name of the print job, and use that as the default filename - but it doesn't.
Is there some other, programatic, way to default the name of the generated XPS file when i print to that printer? i was thinking there might be something like:
a registry key
global shared memory
API call like SetDefaultXPSFilename()
extended attributes about a print job
Example
Automate Excel to create a spreadsheet:
Excel xl = new ExcelApplication();
Workbook wb = xl.Workbooks.Add();
GenerateReport(wb);
wb.PrintOut();
Now if the user's default printer is the Microsoft XPS Document Writer, then the user will get:
i would like a way for that File name to be defaulted to something useful, such as:
20110729 - Chip Bank Settlement Sheet.xps
The user will accept the default filename, and files will organized automatically, rather than the user typing:
asdfadf.xps
References
eggheadcafe: XPS Default File Name
MSDN: XPS Name when Sent to Printer
Bump: 20110729 (12 months later)
Well,
here is a simple way (at least in my case):
(myPrintPage inherits from System.Drawing.Printing.PrintDocument)
With myPrintPage
With .PrinterSettings
If .PrinterName = "Microsoft XPS Document Writer" Then
.PrintToFile = True
.PrintFileName = "c:\test.pdf"
End If
End With
.Print()
End With
I haven't found a way, yet, to determine whether or not the printer I have chosen is going to print into a file, hence the test on the printer's name.
In addition to above, here is a piece of code I found useful:
Let's say that my default printer is NOT the XPS Document Writer. My code needs to archive automatically some data, print a report in XPS, then offer the user to print the report on the default printer. In the second step, I need to change the PrinterSettings of myPrintPage.
Here is how:
'save xps results
'is the XPS printer installed?
Dim myXPSfound As Boolean = False
For Each s As String In System.Drawing.Printing.PrinterSettings.InstalledPrinters
If s.Contains("XPS") Then
myXPSfound = True
Exit For
End If
Next
If myXPSfound Then
'Manual settings of the XPS printerSettings
Dim myXPSPrinterSettings As New Drawing.Printing.PrinterSettings
myXPSPrinterSettings.Collate = False
myXPSPrinterSettings.Copies = 1
myXPSPrinterSettings.Duplex = Drawing.Printing.Duplex.Simplex
myXPSPrinterSettings.FromPage = 0
myXPSPrinterSettings.MaximumPage = 9999
myXPSPrinterSettings.MinimumPage = 0
myXPSPrinterSettings.PrinterName = "Microsoft XPS Document Writer"
myXPSPrinterSettings.PrintRange = Drawing.Printing.PrintRange.AllPages
myXPSPrinterSettings.PrintToFile = True
myXPSPrinterSettings.ToPage = 1
myPrintPage.PrinterSettings = myXPSPrinterSettings
myPrintPage.PrinterSettings.PrintToFile = True
myPrintPage.PrinterSettings.PrintFileName = mytargetFileName & ".xps"
Try
myPrintPage.Print()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Information, "Error Printing the XPS File")
End Try
Else
MsgBox("The Microsoft XPS Writer was no found on this computer", MsgBoxStyle.Information, "Error Printing the XPS File")
End If
It can be handy sometimes.
The Microsoft XPS Document Writer (MXDW) will generate an output file path without prompting the user if the application that prints sets lpszOutput in DOCINFO.
If you don't have access to the code of the application then another option is to build an XPS driver that generates a file path even when lpszOutput hasn't been set. The Windows Driver Kit (WDK) is the place to start.
For more details and links see this post.
Win2PDF 7 can save as XPS, and does default to the name of the print job. If you don't want to use the print job as the name displayed in the File Save dialog, you can change the default file name by setting a registry value named "PDFTitle".
You can also set the output file without prompting either using the lpszOutput field of DOCINFO, or by setting a registry setting named "PDFFileName" as described in the Win2PDF documentation. The file will be created in the XPS format if the file name contains an .xps extension.

Resources