I am using the Word Interop and wish to open a .pdf file and let word automatically do the conversion.
I have the following properties set.
var wordApp = new Word.Application();
wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
wordApp.Options.DoNotPromptForConvert = true;
wordApp.Options.ConfirmConversions = false;
var doc = wordApp.Documents.OpenNoRepairDialog(ExternalFilePath, false, true);
However when it does the Open I still get the following prompt:
Word version 2016.
Does anyone know how to by-pass this? If I click OK the rest of the program executes as I'd expect successfully.
I am aware of and do not wish to use any other third-party tools.
Thanks to BugFinder for the suggestion of using the Format parameter, but still no luck with this.
Here are the additions to the code:
Word.FileConverters converters = wordApp.FileConverters;
var wordPdfConverter = converters.OfType<Word.FileConverter>().Where(c => c.CanOpen == true && c.Extensions == "pdf").First();
var doc = wordApp.Documents.OpenNoRepairDialog(ExternalFilePath, false, true, false, Format: wordPdfConverter.OpenFormat, NoEncodingDialog: true);
This gets a converter but still displays the prompt. :(
Further edit thanks to Cidney's comments. It appear this prompt is a user registry setting as that to bypass it in the interop is impossible. Seems a like a flaw with the Interop to me. The Open XML SDK does not support saving as XPS so this is unavailable too. Appears I will have to manipulate the users registry first to achieve this (brings write permission concerns) or check if Word is waiting for user input and send keys.
Related
Recently I made a program where I take a pdf file and using PDFsharp fill in the form fields with required values. The code that I made works fine it writes the values just fine but the problem comes after you open the pdf and try to close it, you will get a the standard message "Do you want to save changes before closing" even thou you just opened and close the document. The code that I use looks like this:
string templateDocPath = #"Original.pdf";
using (PdfDocument myTemplate = PdfReader.Open(templateDocPath, PdfDocumentOpenMode.Modify))
{
PdfAcroForm form = myTemplate.AcroForm;
if (form.Elements.ContainsKey("/NeedAppearances"))
{
form.Elements["/NeedAppearances"] = new PdfBoolean(true);
}
else
{
form.Elements.Add("/NeedAppearances", new PdfBoolean(true));
}
PdfTextField testField = (PdfTextField)(form.Fields["Name"]);
testField.Value = new PdfString("NameTest");
testField.ReadOnly = true;
myTemplate.Save(#"Output.pdf");
myTemplate.Close();
}
When I was trying to solved the problem I found out that the message comes only after you add "/NeedAppearances" Element to the AcroForms. You need this element or the values you write on the document will not show.
Googling some more I found a forum (https://forum.pdfsharp.net/viewtopic.php?f=2&t=3741) where someone asked the same question but didn't get a clear answer, the last comment mentioned that "/NeedAppearances" says to the document to generate the new values. So when you open the document new values are generated, so you have to save them.
I would like to know if it's true and is there a way to remove the message?
I came across this article yesterday while I was trying to find an answer for the exact problem described in the title. I was never able to find anything from any of the Google searches I ran. However, I was able to figure out what the problem was.
The issue is that when you save the PdfDocument object, it is defaulting the PDF as version 0. You can verify this by opening the generated PDF in Notepad++ (or similar text editor) and looking at the first line. When you open the PDF, Acrobat/Reader has to format it to be able to display it since it is an outdated PDF version; thus causing the document to be changed.
The solution is to set the Version of the PdfDocument before you save (an example of this can be seen here: https://forum.pdfsharp.net/viewtopic.php?f=2&t=617). As of PDFsharp version 1.50, the highest supported version is 17 (see PDFsharp Wiki on which PDF versions are supported).
After struggling whole day, I identified the issue but this didn't solve my problem.
On short:
I need to open a PDF, convert to BW (grayscale), search some words and insert some notes nearby found words. At a first look it seems easy but I discovered how hard PDF files are processed (having no "words" concepts and so on).
Now the first task, converting to grayscale just drove me crazy. I didn't find a working solution either commercial or free. I came up with this solution:
open the PDF
print with windows drivers, some free PDF printers
This is quite ugly since I will force the C# users to install such 3'rd party SW but.. that is fpr the moment. I tested FreePDF, CutePDF and PDFCreator. All of them are working "stand alone" as expected.
Now when I tried to print from C#, obviously, I don't want the print dialog, just select BW option and print (aka. convert)
The following code just uses a PDF library, shown for clarity only.
Aspose.Pdf.Facades.PdfViewer viewer = new Aspose.Pdf.Facades.PdfViewer();
viewer.BindPdf(txtPDF.Text);
viewer.PrintAsGrayscale = true;
//viewer.RenderingOptions = new RenderingOptions { UseNewImagingEngine = true };
//Set attributes for printing
//viewer.AutoResize = true; //Print the file with adjusted size
//viewer.AutoRotate = true; //Print the file with adjusted rotation
viewer.PrintPageDialog = true; //Do not produce the page number dialog when printing
////PrinterJob printJob = PrinterJob.getPrinterJob();
//Create objects for printer and page settings and PrintDocument
System.Drawing.Printing.PrinterSettings ps = new System.Drawing.Printing.PrinterSettings();
System.Drawing.Printing.PageSettings pgs = new System.Drawing.Printing.PageSettings();
//System.Drawing.Printing.PrintDocument prtdoc = new System.Drawing.Printing.PrintDocument();
//prtdoc.PrinterSettings = ps;
//Set printer name
//ps.PrinterName = prtdoc.PrinterSettings.PrinterName;
ps.PrinterName = "CutePDF Writer";
ps.PrintToFile = true;
ps.PrintFileName = #"test.pdf";
//
//ps.
//Set PageSize (if required)
//pgs.PaperSize = new System.Drawing.Printing.PaperSize("A4", 827, 1169);
//Set PageMargins (if required)
//pgs.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0);
//Print document using printer and page settings
viewer.PrintDocumentWithSettings(ps);
//viewer.PrintDocument();
//Close the PDF file after priting
What I discovered and seems to be little explained, is that if you select
ps.PrintToFile = true;
no matter C# PDF library or PDF printer driver, Windows will just skip the PDF drivers and instead of PDF files will output PS (postscript) ones which obviously, will not be recognized by Adobe Reader.
Now the question (and I am positive that others who may want to print PDFs from C# may be encountered) is how to print to CutePDF for example and still suppress any filename dialog?
In other words, just print silently with programmatically selected filename from C# application. Or somehow convince "print to file" to go through PDF driver, not Windows default PS driver.
Thanks very much for any hints.
I solved conversion to grayscale with a commercial component with this post and I also posted there my complete solution, in care anyone will struggle like me.
Converting PDF to Grayscale pdf using ABC PDF
I am using Excel Interop to open an xlsx file and save that as a pdf document. Upon invoking the 'ExportAsFixedFileFormat' method a dialog titled "Publishing" is displayed to indicate the progress. How can I suppress or hide this dialog? I have seen a few similar questions on other forums without a satisfying solution, but hopefully someone has solved this since then.
Code:
Application application = new Application();
application.DisplayAlerts = false; // <- No effect
application.Visible = false; // <- No effect
application.ScreenUpdating = false; // <- No effect
application.UserControl = false; // <- No effect
application.Workbooks.Open(path, Type.Missing, true);
application.DisplayDocumentActionTaskPane = false; // <- No effect
application.Worksheets[1].ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, path);
Perhaps I am not answering your question, but I'll try to be helpful. As far as I know, it's not recommended to use Excel Interop in back-end processing. You encountered one of its issues, but there are some others. There are 3rd party alternatives for interacting with Excel formats, some of them are open source and some are commercial. I would strongly recommend taking a look at one of them:
ClosedXML and NPOI. Both are open source and free.
How about processing it on a BackgroundWorker. This will not throw COMEXCEPTION.
I tried this code on a button click and it works without displaying the progress dialog.
var worker = new BackgroundWorker();
worker.DoWork += (o, args) =>
{
var path = #"D:\sample.xlsx";
var application = new Microsoft.Office.Interop.Excel.Application();
application.Workbooks.Open(path,
Type.Missing, true);
application.Worksheets[1].ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, path);
};
worker.RunWorkerAsync();
You can use pedamorf library ,pedamorf is a server that converts documents, images, urls, html and text to PDF. It relies heavily upon the excellent open-source programs wkhtml2pdf, Libre Office and iTextSharp. A client library is provided and can be used from a .NET application to utilize the conversion services provided by pedamorf.
More info is here
By far the better API to handle (create, read, export to PDF/html, etc...) XLS/XLSX files that I know is FlexCel. It's really simple, incredibly fast and full writen in C#. Don't require Excel instalation.
You'll find it here : http://www.tmssoftware.com/site/flexcelnet.asp (get the trial version with a lot of examples with source code)
If you have budget in your project to acquire the licence, I realy reccomend.
I try to implement a custom Wopi host in C# that can handle the Cobalt Protocol using the CobaltCore assembly.
But I didn't found any documentation for CobaltCore.dll
Object browser is a little helpful..
Please provide some details if someone had similar issue.
How I should use Cobalt to decipher the messages?
For word editing implementation go here:
Can I just use Office Web Apps Server
// fsshttpb payload, basically decode from base64 encoded
byte[] test1 = System.Convert.FromBase64String("DAALAJzPKfM5lAabBgIAAO4CAABaBBYADW1zd29yZAd3YWN6AggA1RyhD3cBFgIGAAMFABoEIAAL3Do4buY4RJXm4575cgEiigICAAALAawCAFUDAQ==");
// create an atom object from the fsshttp input
AtomFromByteArray atomRequest = new AtomFromByteArray(test1);
RequestBatch requestBatch = new RequestBatch();
requestBatch.DeserializeInputFromProtocol(atomRequest);
// now you can inspect requestBatch to view the decoded objects
edit:
Here is a sample implementation using CobaltCore. Pretty much a combination of my answers about WOPI/FSSHTTP on this website in one project.
https://github.com/thebitllc/WopiBasicEditor
Also implementing the Cobalt approach to edits and like Julia it stops at a "cant edit screen" even after lockingstore callbacks including co-author etc.
What I have found however is the log system for OWA reveals quite considerable detail about what the OWA server is attempting to do.
C:\ProgramData\Microsoft\OfficeWebApps\Data\Logs\ULS
I can see from these logs it complains about a missing access token, by providing
&access_token=1&access_token_ttl=0
to the end of the wopi url this error goes away.
I also tested many of the file info fields and was able to see how the OWA server caches information. If we keep changing the cfi.Version
FileInfo info = new FileInfo("C:\\WOPI OWA WORD EDITOR\\OWA_Source_Documents\\" + fi.Name);
cfi.Version = info.LastWriteTimeUtc.ToString("s");
we get a fresh cached item each time we change the files contents via normal word.
These also affect the View mode for Word and I suspect will lock us out of the word edit mode but since I don't have that working I cant tell yet.
cfi.SupportsCoauth = true; // all three (3) needed to see the edit in browser menu in view mode .
cfi.SupportsCobalt = true; // all three (3) needed to see the edit in browser menu in view mode .
cfi.SupportsFolders = true; // all three (3) needed to see the edit in browser menu in view mode .
cfi.SupportsLocks = true;
cfi.SupportsScenarioLinks = false;
cfi.SupportsSecureStore = true;
cfi.SupportsUpdate = true;
This one locks out the word edit function and unless you update the version of the file it will stay locked even if you change it back to false.
cfi.WebEditingDisabled = false;
Roger Hogg
thanks to thebitllc for the correct approach to getting back the file.
System.IO.FileStream _FileStream = new System.IO.FileStream("C:\\WOPI OWA WORD EDITOR\\OWA_Updated_Documents\\output.docx", System.IO.FileMode.Create, System.IO.FileAccess.Write);
GenericFdaStream myCobaltStream = new GenericFda(cobaltFile.CobaltEndpoint, null).GetContentStream();
myCobaltStream.CopyTo(_FileStream);
_FileStream.Close();
I am using iTextSharp for reading and managing PDF documents. Things such as stamping overlays for the background or logos and backers. The PDF's are statement files, so I cannot give an example. I am wondering how to view the settings of the PDF to see if the PDF file is Simplex or Duplex, and that sort of information. Any help or suggestions would be appreciated. At the moment I test for certain criteria of second page, and this is a poor and bad way to do this. Thanks in advance, and happy coding!
The duplex mode is stored in the document's /ViewerPreferences dictionary under the /Duplex key. It supports three values, /DuplexFlipLongEdge, /DuplexFlipShortEdge, and /Simplex. You can use the code below to inspect this:
//Assume false by default since this was introduced in PDF 1.7
Boolean isDuplex = false;
//Bind a reader to our file
using (var r = new PdfReader(testFile)) {
//Get the view preferences
var prefs = r.Catalog.GetAsDict(PdfName.VIEWERPREFERENCES);
//Make sure we found something
if (prefs != null) {
//Get the duplex key
var duplex = prefs.Get(PdfName.DUPLEX);
//Make sure we got something and it is one of the duplex modes
isDuplex = (duplex != null && (duplex.Equals(PdfName.DUPLEXFLIPLONGEDGE) || duplex.Equals(PdfName.DUPLEXFLIPSHORTEDGE)));
}
}
I know its 2 years later but I just spent hours searching, found this... but eventually found...
I create a button that runs this script (that pops up the printer dialogue with duplex pre selected if available... note that selecting another printer erases this pre selection.. also change "Long" for "Short" if you flip that way... q8)
var pp = this.getPrintParams();
pp.DuplexType = pp.constants.duplexTypes.DuplexFlipLongEdge;
this.print(pp);