CMMaung
CMMaung

Reputation: 165

Microsoft Word Template for Report Using ASP.NET C#

When I run with debugging mode in my local machine, it's okay but on server I got an error like this.

Retrieving the COM class factory for component with CLSID {00020906-0000-0000-C000-000000000046} failed due to the following error: 80080005.

My server is Windows 2008 64 bit, Office 2007 and my code is like this

private void GenerateWords(string sPO, string sSup)
    {
        Object oMissing = System.Reflection.Missing.Value;
        Object oTrue = true;
        Object oFalse = false;
        Object savechanges = true;

        Word.ApplicationClass oWord = new Word.ApplicationClass();
        Word.Document oWordDoc = new Word.Document();
        oWord.Visible = true;
        Object oTemplatePath = Server.MapPath("Reports/Word/PurchaseOrder.docx");            

        oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);            
        oWordDoc.Activate();

        foreach (Word.Field myMergeField in oWordDoc.Fields)
        {
            iTotalFields++;
            Word.Range rngFieldCode = myMergeField.Code;
            String fieldText = rngFieldCode.Text;

            // Start filling information in Word file
            if (fieldText.StartsWith(" MERGEFIELD"))
            {
                Int32 endMerge = fieldText.IndexOf("\\");
                Int32 fieldNameLength = fieldText.Length - endMerge;
                String fieldName = fieldText.Substring(11, endMerge - 11);

                fieldName = fieldName.Trim();

                if (fieldName == "PONo")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(sPO);
                }

                if (fieldName == "SupNo")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(sSup);
                }

                if (fieldName == "VendorID")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["VendorID"].ToString().Trim());
                }

                if (fieldName == "VName")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Name"].ToString().Trim());
                }

                if (fieldName == "Contact")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Contact"].ToString().Trim());
                }

                if (fieldName == "Designation")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Designation"].ToString().Trim());
                }

                if (fieldName == "Tel")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Tel"].ToString().Trim());
                }

                if (fieldName == "Fax")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Fax"].ToString().Trim());
                }

                if (fieldName == "PODate")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["PODate"].ToString().Trim());
                }

                if (fieldName == "ClientName")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["ClientName"].ToString().Trim());
                }

                if (fieldName == "JobDescription")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["JobDescription"].ToString().Trim());
                }

                if (fieldName == "JobNo")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["JobNo"].ToString().Trim());
                }

                if (fieldName == "CostCode")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["CostCode"].ToString().Trim());
                }

                if (fieldName == "SchDlvy")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["SchDlvy"].ToString().Trim());
                }

                if (fieldName == "DlvyPoint")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["DlvyPoint"].ToString().Trim());
                }

                if (fieldName == "Amount")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Amount"].ToString().Trim());
                }

                if (fieldName == "tbl")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeParagraph();
                    Word.Table tbl = oWordDoc.Tables.Add(rngFieldCode, 1, 5, ref oMissing, ref oMissing);
                    //oWordDoc.Tables.Add(rngFieldCode, dtItems(sPO, sSup).Rows.Count, 5, ref oMissing, ref oMissing);

                    //SET HEADER
                    SetHeadings(tbl.Cell(1, 1), "Item No.");
                    SetHeadings(tbl.Cell(1, 2), "Description");
                    SetHeadings(tbl.Cell(1, 3), "Unit");
                    SetHeadings(tbl.Cell(1, 4), "Unit Price");
                    SetHeadings(tbl.Cell(1, 5), "Amount");
                    //END SET HEADER

                    //Add Row
                    for (int i = 0; i < dtItems(sPO, sSup).Rows.Count; i++)
                    {
                        Word.Row newRow = tbl.Rows.Add(ref oMissing);
                        newRow.Range.Font.Bold = 0;
                        newRow.Range.Underline = 0;
                        newRow.Range.ParagraphFormat.Alignment =
                        Word.WdParagraphAlignment.wdAlignParagraphCenter;

                        newRow.Cells[1].Range.Text = dtItems(sPO, sSup).Rows[i][3].ToString();
                        newRow.Cells[2].Range.Text = dtItems(sPO, sSup).Rows[i][4].ToString();
                        newRow.Cells[3].Range.Text = dtItems(sPO, sSup).Rows[i][8].ToString();
                        newRow.Cells[4].Range.Text = dtItems(sPO, sSup).Rows[i][10].ToString();
                        newRow.Cells[5].Range.Text = dtItems(sPO, sSup).Rows[i][11].ToString();
                    }
                    //END ROW

                    oWord.Selection.TypeParagraph();
                }

                if (fieldName == "TItems")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtTotal(sPO, sSup).Rows[0]["Unit"].ToString().Trim());
                }

                if (fieldName == "Discount")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtTotal(sPO, sSup).Rows[0]["Discount"].ToString().Trim());
                }

                if (fieldName == "TAmount")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtTotal(sPO, sSup).Rows[0]["Amount"].ToString().Trim());
                }

                if (fieldName == "Summary")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["Amount"].ToString().Trim());
                }

                if (fieldName == "ReqNo")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["ReqNo"].ToString().Trim());
                }

                if (fieldName == "RevNo")
                {
                    myMergeField.Select();
                    oWord.Selection.Font.Color = Word.WdColor.wdColorBlue;
                    oWord.Selection.TypeText(dtPOSup(sPO, sSup).Rows[0]["RevNo"].ToString().Trim());
                }
            }
        }
        // End filling information in Word file

        Object oSaveAsFile = (Object)Server.MapPath("Reports/Word/tmp2.docx");
        oWordDoc.SaveAs(ref oSaveAsFile, 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, ref oMissing);

        oWordDoc.Close(ref savechanges, ref oMissing, ref oMissing);
        oWord.Application.Quit(ref savechanges, ref oMissing, ref oMissing);

        //foreach (Process p in System.Diagnostics.Process.GetProcessesByName("winword"))
        //{
        //    try
        //    {
        //        if (p.ProcessName == "WINWORD")
        //        {
        //            if (!p.HasExited)
        //            {
        //                p.Kill();
        //                p.WaitForExit(); // possibly with a timeout
        //            }
        //        }
        //        else
        //        {
        //            lblMessage.Text = "cannot kill. try again!";
        //        }
        //    }
        //    catch (Win32Exception winException)
        //    {
        //        //process was terminating or can't be terminated - deal with it    
        //        Session["error"] = winException.Message;
        //        Response.Redirect("MessageBoard.aspx");
        //    }
        //    catch (InvalidOperationException invalidException)
        //    {
        //        //process has already exited - might be able to let this one go  
        //        Session["error"] = invalidException.Message;
        //        Response.Redirect("MessageBoard.aspx");
        //    }
        //}   

        Response.ClearContent();
        Response.ClearHeaders();
        Response.ContentType = "application/msword";
        Response.WriteFile(Server.MapPath("Reports/Word/tmp2.docx"), false);
        Response.Flush();
        Response.Close();
    }

And I followed to give the permission from Blog.Crowe.co.nz But still got problem, I can't solve this one since last month. If you're possible, please kindly help to me. Thanks

Upvotes: 0

Views: 2964

Answers (3)

Jed
Jed

Reputation: 1

I had this exact error with an ASP.NET site using a COM object on Windows 2008 64-bit. The solution I finally found was to re-register the COM dll with regsvr32 and also set the IIS Application pool's "Enable 32-bit applications" property to true. It worked fine after that. I wasn't working with MS Word, so I can't say with 100% certainty that this will work for you, but it should at least be worth a try.

Upvotes: 0

shawty
shawty

Reputation: 5829

It's generally a very bad idea to use the full blown office suite for processes like this in a server environment.

Office is primarily designed as a client app to be run on an interactive desktop. When running server side you realistically need an untended way of doing things.

You can get office server side components, but I'm not 100% sure on all the pros and cons of doing so.

If your creating word 2007 compatible documents then you might want to look at using the "Open XML" format (Which is what word 2007 onwards uses), Microsoft provide an Open XML SDK for performing such tasks

you can find the docs here: http://msdn.microsoft.com/en-us/library/bb226703.aspx

If you must use the full blown office suite, then I could suggest that you try opening word manually on the server, as the user that your web app will run as. You can then dismiss the initals box and set it never to appear again, that should (In theory) prevent the problem your seeing from re-occurring. It does not however mean that you'll get 100% problem free use from that point on, using the Office com interop poses way to many problems in a server environment.

More details on Microsoft's own approach can be found here : http://support.microsoft.com/kb/257757

Upvotes: 1

jfrankcarr
jfrankcarr

Reputation: 481

The short answer is that this isn't supported by Microsoft so don't expect it to work or work reliably.

The long answer is that the issue is permissions and how Word works. The link you posted shows how to get around this for Excel but this won't work for Word. The problem is that when Word is called for the first time it wants to display a welcome dialog where the user can enter initials and other stuff. When it's run via IIS, the dialog doesn't show and the COM object can't be created. There are supposed to be some ways to disable this dialog but Microsoft only seems to make them available to volume licenses. Other than that, the way to do it is to try to run Word on the server using the IIS built-in user account and get rid of the first time user dialog that way.

Another way I've done this back in the classic ASP days was to use a COM+ object with its own processing space and user permissions. This worked well but I haven't tried it with ASP.NET. This is a good option if your net admin doesn't want to give permissions to the IIS built-in directly.

The last solution is to scrap using Word entirely and use a different method to generate your documents. This is the direction I went because memory usage issues between Word and IIS kept causing server crashes during load testing which were unacceptable.

Additional Info:

As for alternative methods dynamically generating Word docs, you can use a RTF template file. Just create your own tokens in the text where you can do a find/replace on the data fields. Word reads/writes RTF files so you just have to train users sometimes. There are also third party tools available that will create Word docs but they're pricey and I haven't used any of them.

Upvotes: 0

Related Questions