views:

377

answers:

6

How can I convert an RTF file to a PDF one? I have the adobe PDF printer, should I use it? If so, how can I programmatically access it?

A: 

An RTF document has to be read and interpreted by some app that can understand that format. You would need to programmatically launch that app, load your RTF file, and send it to the PDF printer. Word would be good for that, since it has a nice .NET interface. An overview of the steps would be:

ApplicationClass word = new ApplicationClass();
Document doc = word.Documents.Open(ref filename, ...);
doc.PrintOut(...);

You will need to use the Microsoft.Office.Interop.Word namespace and add a reference to the Microsoft.Office.Interop.Word.dll assembly.

CesarGon
Yes I can, but how would I do so?
Malfist
Editing answer to add information.
CesarGon
This will work fine, but not in a server environment. Microsoft does not recommend or support using the Office API in a server environment. See for example question 159744.
glaxaco
Fair enough, but nothing in the question points to a server environment. :-)
CesarGon
A: 

ITextSharp should do the trick for you.

klabranche
Care to explain a little bit more?
Malfist
supposedly it can't be done: http://stackoverflow.com/questions/1095846/can-itextsharp-open-an-rtf-document-manipulate-it-and-export-the-document-to-pd
Malfist
Warning - As I researched a little more it seems the functionality for this is NOT complete yet. At least that's what I found from a response on a question from Jan. 2009.
klabranche
+1  A: 

You could use the virtual print Driver doPdf http://www.dopdf.com/ if this is permitted on the production machine. This will convert more or less any file type to a pdf format not just rtf. It just appears as another printer within Print Manager once installed.

To use it in say winforms code I adapted the code found on the msdn printing example http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx

private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            streamToPrint = new System.IO.StreamReader
               (@"F:\temp\labTest.txt");
            try
            {
                printFont = new Font("Arial", 10);
                PrintDocument pd = new PrintDocument();
                pd.PrinterSettings.PrinterName = "doPDF v6";//<-------added
                pd.PrintPage += new PrintPageEventHandler
                   (this.pd_PrintPage);
                pd.Print();
            }
            finally
            {
                streamToPrint.Close();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

The only part of the code I needed to add was that marked above e.g. pd.PrinterSettings.PrinterName = "doPDF v6";

There may be a printer enumeration method which would be more elegant and robust and against this one could test to see if the print driver existed perhaps against a config file setting.

Update: Handling multiple pages is taken care of in this method : this.pd_PrintPage as per the msdn sample. PrintDocument supports from and to page printing. DoPdf will pops up a fileSaveAsDialog box automatically so the files can be saved as a pdf document.

What about rtf though? A Microsoft format not supported very well so it would seem. This article http://msdn.microsoft.com/en-us/library/ms996492.aspx with demo code uses the RichTextBox as a starting point and by using P/Invoke leverages the power of Win32 to print RTF as WYSIWG. The control defines it's own page length method replacing the one used above in the code snippet and still uses PrintDocument so it should be easy to use. You can assign any rtf using Rtb.rtf method.

Andrew
Close, but a complete answer would include how to print RTF (with Paging etc). Also you probably want a PDF printer that let's you set the output filename.
Henk Holterman
@Henk, I have editted the article (added a piece at the end) that should address all the points you raise.
Andrew
Doesn't work because it just prints the text of the RTF file, I.E. not the human readable part of it. It prints what would print if I opened the RTF file in Notepad.
Malfist
@Malfist - did you adapt the code above using the article I referenced in the update section of my answer. I was seeing the human readable output as displayed by the Rtb and not the behaviour you describe which defeats the whole object of the exercise.
Andrew
+1  A: 

See this article. It looks like you can use it without many modifications. It uses Open Office.

Roman Boiko
There is source code available for download.
Roman Boiko
A: 

Actually, none of these are terribly reliable or do what I want. The solution is simple, install Adobe Acrobat and just have it open the RTF file using the Process class.

I also found a more reasonable approach. I save the file as an RTF, the open it in word, and save it as PDF (Word's Print As PDF plugin must be installed)

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Personal Document File (*.pdf)|*.pdf";
            if (sfd.ShowDialog() == DialogResult.OK) {
                String filename = Path.GetTempFileName() + ".rtf";
                using (StreamWriter sw = new StreamWriter(filename)) {
                    sw.Write(previous);
                }


                Object oMissing = System.Reflection.Missing.Value;    //null for VB
                Object oTrue = true;
                Object oFalse = false;

                Microsoft.Office.Interop.Word.Application oWord = new Microsoft.Office.Interop.Word.Application();
                Microsoft.Office.Interop.Word.Document oWordDoc = new Microsoft.Office.Interop.Word.Document();

                oWord.Visible = false;
                Object rtfFile = filename;
                Object saveLoc = sfd.FileName;
                Object wdFormatPDF = 17;    //WdSaveFormat Enumeration
                oWordDoc = oWord.Documents.Add(ref rtfFile, ref oMissing, ref oMissing, ref oMissing);
                oWordDoc.SaveAs(ref saveLoc, ref wdFormatPDF, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                     ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);

                oWordDoc.Close(ref oFalse, ref oMissing, ref oMissing);
                oWord.Quit(ref oFalse, ref oMissing, ref oMissing);

                //Get the MD5 hash and save it with it
                FileStream file = new FileStream(sfd.FileName, FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();

                using (StreamWriter sw = new StreamWriter(sfd.FileName + ".md5")) {
                    sw.WriteLine(sfd.FileName + " - " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString() + " md5: " + BinaryToHexConverter.To64CharChunks(retVal)[0]);
                }
            }
Malfist
A: 

maybe you can try simpo pdf creator which works as a virtul printer can print your file into pdf format.and many people recommend it.if you wish you can have a try.http://www.simpopdf.com/pdf-creator.html

kethy