4

I have tried to write data from FileStream, StreamWriter to a word file.

It's working fine when the data is text format(using StreamWriter). But when I tried the same with Binarywriter (for writing image to word doc) it's writing incorrectly to the word document.

In below code lstOrderedSpares[index].SparePicture is the byte array containing the image data.

I need a solution without OPENXML.

This is what I have tried so far :

Here is my button click where i am initializing the data to classes and List

 private void btnCreateQuotation_Click(object sender, EventArgs e)
    {
        try
        {
            Quotation aQuotation = new Quotation();
            aQuotation.QuotationId = quotationId;
            aQuotation.QuotationDate = lblQuotationDateValue.Text;

        //Reading from Datagridview and adding to List<Spare>

            List<Spare> lstOrderedSpares = new List<Spare>();
            if (dataGridView1.Rows.Count > 0)
            {
                foreach (DataGridViewRow dr in dataGridView1.Rows)
                {
                    Spare aSpare = new Spare();
                    aSpare.SapreSerialNumber = dr.Cells["SlNo"].Value.ToString();
                    aSpare.SparePartId = dr.Cells["SparePartID"].Value.ToString();
                    aSpare.SparePicture = (byte[])dr.Cells["SparePicture"].Value;
                    aSpare.SpareDescription = dr.Cells["SpareDescription"].Value.ToString();
                    aSpare.EURPrice = Convert.ToDouble(dr.Cells["EURPrice"].Value.ToString());
                    aSpare.Quantity = Convert.ToDouble(dr.Cells["Quantity"].Value.ToString());
                    aSpare.TotalPrice = Convert.ToDouble(dr.Cells["TotalPrice"].Value.ToString());
                    aSpare.DeliveryCharge = Convert.ToDouble(txtDeliveryCharge.Text.Trim());
                    aSpare.Vat = txtVAT.Text.Trim();
                    aSpare.INRPrice = Convert.ToDouble(dr.Cells["INRPrice"].Value.ToString());
                    lstOrderedSpares.Add(aSpare);
                }
            }

            Contact aContact = new Contact();
            aContact.CompanyName = txtCustomerName.Text.Trim();
            aContact.ContactName = cmbContactPersonName.Text;
            aContact.ContactId = Convert.ToInt32(lblContactPeronIdValue.Text);
            aContact.CompanyId = Convert.ToInt32(lblCustomerIDValue.Text);

            string fileName = "SparePart_" + aQuotation.QuotationId + "_";
            string fileNameWithPath = "C:\\Quotations\\SpareQuotations\\" + fileName;
            if (isaddedtodb)
            {
                CreateDocument(aQuotation, aContact, lstOrderedSpares, fileNameWithPath);

                fileNameWithPath = fileNameWithPath + aContact.CompanyName.Trim() + ".doc";
                btnCreateQuotation.Visible = false;
                this.Hide();
                //start ms word to open the document 
                System.Diagnostics.Process.Start(fileNameWithPath);
            }
        }
        catch (Exception objEx)
        {

        }
    }

and here is the CreateDocument Method which writes data to the word document.

 private void CreateDocument(Quotation aQuotation, Contact aContact,
                                List<Spare> lstOrderedSpares, string fileNameWithPath)
    {
        try
        {
            _Application oWord = new Microsoft.Office.Interop.Word.Application();
            _Document oDoc = oWord.Documents.Add();
            oWord.Visible = true;


            //modify secondparameter to include customer name in file name 
            fileNameWithPath = fileNameWithPath + aContact.CompanyName.Trim() + ".doc";

            //Insert text
            Range rng = oDoc.Range();
            rng.Text = "TSV/" + aQuotation.EnquiredBy.ToString() + "/JS/" + aQuotation.QuotationId
                    + "/SPARES" + "\t" + "\t" + "\t" + "\t" + "\t" + aQuotation.QuotationDate;
            //oWord.Selection.EndKey();
            //oWord.Selection.TypeParagraph();
            rng.InsertBreak();
            rng.Text = "To ,";
            rng.InsertBreak();
            rng.Text = "M/s. " + aContact.CompanyName + ",";
            rng.InsertBreak();
            rng.Text = aContact.AddressLine1 + ",";
            rng.InsertBreak();
            rng.Text = aContact.AddressLine2 + ",";
            rng.InsertBreak();
            rng.Text = aContact.City + "," + aContact.State + ",";
            rng.InsertBreak();
            rng.Text = aContact.Country + "-" + aContact.PinNo;
            rng.InsertBreak();
            rng.Text = "Phone : " + aContact.PhoneNo;
            rng.InsertBreak();
            rng.Text = "Mobile No : " + aContact.MobileNo;
            rng.InsertBreak();
            rng.InsertBreak();

            //Salutation and subject

            rng.Text = "\t" + "\t" + "Kind Attention : " + aContact.ContactName;
            rng.InsertBreak();
            rng.Text = "Dear Sir,";
            rng.InsertBreak();
            rng.Text = "Sub: " + aQuotation.Subject;
            rng.InsertBreak();
            rng.Text = "Ref: your email enquiry dt: " + aQuotation.EmailEnquiredDate;
            rng.InsertBreak();
            rng.Text = "We thank you for your valuable email enquiry dt. " + aQuotation.EmailEnquiredDate
                             + " for supply of spares for your .........Capacity,"
                             + " fabrik nos Sl. No :..................";
            rng.InsertBreak();
            rng.InsertBreak();
            int europeancount = 0;
            for (int index = 0; index < lstOrderedSpares.Count; index++)
            {
                if (lstOrderedSpares[index].INRPrice == 0.00)
                {
                    europeancount++;
                }
            }

            rng.Text = "A) We wish to inform you that the following " + europeancount +
                             " spares can be supplied directly by in Euros.";
            rng.InsertBreak();
            rng.InsertBreak();

            int tempslno1 = 0;
            for (int index = 0; index < lstOrderedSpares.Count; index++)
            {
                if (lstOrderedSpares[index].INRPrice == 0.00)
                {
                    tempslno1++;
                    rng.Text = tempslno1 + "." + lstOrderedSpares[index].SpareDescription.ToUpper() +
                                 " : ARTICLE NO: " + lstOrderedSpares[index].SparePartId + "\t" +
                                 Math.Round(lstOrderedSpares[index].EURPrice) + lblEuroSymbol.Text + "(" +
                    new NumberToEnglish().changeCurrencyToWords(Math.Round(lstOrderedSpares[index].EURPrice)) + ")";

                    //To insert a picture from a byte array you need to use the Clipboard to paste it in
                    object endOfContent = oDoc.Content.End - 1;
                    Range rngPic = oDoc.Range(endOfContent);
                    //Here is the trick to convert the ByteArray into an image and paste it in the document
                    Image sparePicture = ByteArrayToImage(lstOrderedSpares[index].SparePicture);
                    Clipboard.SetDataObject(sparePicture);
                    rngPic.Paste();
                    rng.InsertBreak();
                }
            }
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "Price Quoted Ex-works .";
            rng.InsertBreak();
            rng.Text = "Freight/Courier,Insurance,duties,any and all other expenses extra to " +
                             "customers account.";
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "HOW TO ORDER :- Please register your order in favour of ....";
            rng.InsertBreak();
            rng.Text = "PAYMENT :- Full payment in advance against proforma invoice from ...." + " through their bankers ..... ";
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "Delivery / Dispatch: 2 Weeks from the date of receipt of payment.";
            rng.InsertBreak();
            rng.Text = "In case if you have account with ...then kindly mention the account number, " +
                             "since it will be economical if send via ....";
            rng.Text = "Please provide your 'IEC Code number'.";
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "B) We wish to inform you that the following spare can be supplied from ex-stock " + "our Office in INR";
            rng.InsertBreak();
            int tempslno2 = 0;
            for (int index = 0; index < lstOrderedSpares.Count; index++)
            {

                if (lstOrderedSpares[index].INRPrice != 0.00)
                {
                    tempslno2++;
                    rng.Text = tempslno2 + "." + lstOrderedSpares[index].SpareDescription.ToUpper() +
                                 " : ARTICLE NO: " + lstOrderedSpares[index].SparePartId + "\t" +
                                 Math.Round(lstOrderedSpares[index].INRPrice) + " " + lblINRSymbol.Text + "(" +
                    new NumberToEnglish().changeNumericToWords(Math.Round(lstOrderedSpares[index].INRPrice)) + ")";

                    //To insert a picture from a byte array you need to use the Clipboard to paste it in
                    object endOfContent = oDoc.Content.End - 1;
                    Range rngPic = oDoc.Range(endOfContent);
                    //Here is the trick to convert the ByteArray into an image and paste it in the document
                    Image sparePicture = ByteArrayToImage(lstOrderedSpares[index].SparePicture);
                    Clipboard.SetDataObject(sparePicture);
                    rngPic.Paste();
                    rng.InsertBreak();
                }
            }

            rng.Text = "Price quoted ex-our office";
            rng.InsertBreak();
            rng.Text = "Taxes: VAT TNGST @ " + lstOrderedSpares[0].Vat + "% extra";
            rng.InsertBreak();
            rng.Text = "Delivery/Despatch: on receipt of order along with payment";
            rng.Text = "Delivery/Courier Charges - extra " + lstOrderedSpares[0].DeliveryCharge.ToString() +
                            "/-";                
            rng.InsertBreak();
            rng.Text = "The order & payment may please be released in favour of...";
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "Payment: Full payment in advance by way of Electronic Transfer as per following details :";
            rng.InsertBreak();
            rng.Text = "Current Account Number: ......";
            rng.InsertBreak();
            rng.Text = "IFSC Code: ..........";
            rng.InsertBreak();
            rng.Text = "Name of the account holder: .........";
            rng.InsertBreak();

            rng.Text = "\t" + "\t" + "\t" + "OR";
            rng.InsertBreak();
            rng.Text = "By way of Demand Draft";
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "Offer validity 30 days";
            rng.InsertBreak();
            rng.Text = "Thanking you and awaiting your valuable instructions to fulfill your needs well in time.";
            rng.InsertBreak();
            rng.InsertBreak();
            rng.Text = "Yours sincerely";
            rng.InsertBreak();

            oWord.Selection.EndKey();
            oWord.Selection.TypeParagraph();

            oDoc.SaveAs(fileNameWithPath);  //If you're creating a document
            oDoc.Close();
            oWord.Quit();
        }
        catch (Exception objEx)
        {

        }
    }

    public Image ByteArrayToImage(byte[] byteArrayIn)
    {
        MemoryStream ms = new MemoryStream(byteArrayIn);
        Image returnImage = Image.FromStream(ms);
        returnImage = ResizeImage(returnImage, new Size(30, 30));
        return returnImage;
    }

    public static Image ResizeImage(Image imgToResize, Size size)
    {
        return (Image)(new Bitmap(imgToResize, size));
    }
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Chandan Kumar
  • 4,570
  • 4
  • 42
  • 62
  • do a google search http://msdn.microsoft.com/en-us/library/office/bb497430(v=office.15).aspx – MethodMan Oct 25 '14 at 20:44
  • @DJKRAZE - i want to achieve this using BinaryWriter or any class available in IO Namespace. Is it possible or not ? – Chandan Kumar Oct 25 '14 at 20:48
  • do a google searh C# how to insert picture into MSWord doc using BinaryWriter – MethodMan Oct 25 '14 at 20:56
  • @DJKRAZE i have googled and unfortunately not finding any solution. That's why posted here. Any help will be appreciated. – Chandan Kumar Oct 25 '14 at 21:03
  • [C# stackoverflow save image to msword doc using BinaryWriter](https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=C%23%20stackoverflow%20save%20image%20to%20msword%20doc%20using%20BinaryWriter) – MethodMan Oct 25 '14 at 21:05
  • @DJKRAZE - i am sorry. I need a solution without OPENXML.i have gone through the links but those are only for OPENXML. – Chandan Kumar Oct 25 '14 at 21:37
  • https://social.msdn.microsoft.com/Forums/office/en-US/036e0f31-7829-4e6f-8495-d15830f2205e/how-to-automate-inserting-pictures-one-after-the-other-in-ms-word-document-using-c?forum=worddev you need to do you google search in the future using `Microsoft.Interop` in your google search the link when you check it out scroll down to the second from the bottom answer and start creating a solution from what's there.. – MethodMan Oct 25 '14 at 22:26

1 Answers1

12

When you create a file, eg C:\Temp\MyWordDoc.doc and write data to it using a FileStream and StreamWriter, you're actually writing information to a text file.

The doc or docx file extension causes Microsoft Word to open the file, but it is NOT in Word format, its just plain text.

You need to use the MS Word Object Model to add pictures into a word document. To do this reference the Microsoft.Office.Interop.Word .Net DLL in your project and try this code:

using Microsoft.Office.Interop.Word;
using System.IO;

private void btnCreateQuotation_Click(object sender, EventArgs e)
{
    var spareList = new List<Spare>();
    spareList.Add(new Spare{ SparePicture  = ImageToByteArray(Image.FromFile(@"C:\temp\11.png"))});
    spareList.Add(new Spare { SparePicture = ImageToByteArray(Image.FromFile(@"C:\temp\1.png")) });
    CreateDocument(@"C:\Temp\MyWordDoc.docx", spareList);
}

public void CreateDocument(string docFilePath, List<Spare> lstOrderedSpares)
{
    Microsoft.Office.Interop.Word._Application oWord = new Microsoft.Office.Interop.Word.Application();
    Microsoft.Office.Interop.Word._Document oDoc = oWord.Documents.Add(); //If you're creating a document
    //Microsoft.Office.Interop.Word._Document oDoc = oWord.Documents.Open(docFilePath, ReadOnly: false, Visible: true); //If you're opening a document

    //To see whats going on while populating the word document set Visible = true
    oWord.Visible = true;

    //Insert text
    Object oMissing = System.Reflection.Missing.Value;
    var oPara1 = oDoc.Content.Paragraphs.Add(ref oMissing);
    oPara1.Range.Text = "First Text";
    oPara1.Range.InsertParagraphAfter();

    //Here is the trick to insert a picture from a byte array into MS Word you need to 
    //convert the ByteArray into an Image and using the Clipboard paste it into the document
    Image sparePicture = ByteArrayToImage(lstOrderedSpares[0].SparePicture);
    Clipboard.SetDataObject(sparePicture);
    var oPara2 = oDoc.Content.Paragraphs.Add(ref oMissing);
    oPara2.Range.Paste();
    oPara2.Range.InsertParagraphAfter();

    //Insert some more text
    var oPara3 = oDoc.Content.Paragraphs.Add(ref oMissing);
    oPara3.Range.Text = "Second Text" + Environment.NewLine;
    oPara3.Range.InsertParagraphAfter();

    sparePicture = ByteArrayToImage(lstOrderedSpares[1].SparePicture);
    Clipboard.SetDataObject(sparePicture);
    var oPara4 = oDoc.Content.Paragraphs.Add(ref oMissing);
    oPara4.Range.Paste();
    oPara4.Range.InsertParagraphAfter();

    oDoc.SaveAs(docFilePath); //If you're creating a document
    //oDoc.Save();  //If you're opening a document
    oDoc.Close();
    oWord.Quit();
}

public Image ByteArrayToImage(byte[] byteArrayIn)
{
    using (MemoryStream ms = new MemoryStream(byteArrayIn))
    {
      Image returnImage = Image.FromStream(ms);
      return returnImage;
    }
}

//Method I use to test loading images from disk into byte[]'s and inserting them into word
public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
    byte[] result = null;
    using (MemoryStream ms = new MemoryStream())
    {
        imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        result = ms.ToArray();
    }
    return result;
}

This is the result:

enter image description here

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • @kumarch1 how's everything going? Did you get it working? Let me know if you need a hand or have any questions. – Jeremy Thompson Nov 07 '14 at 01:02
  • What should i do if i need to write more text after image ? Actually i was handling this using streamwriter with filestream. but as per now i have replaced all text data with rng.text. Then as per your suggestion i am writing image and again writing text using rng.text. Word document is created without anything - means blank word doc created. – Chandan Kumar Nov 07 '14 at 03:54
  • And one more thing, i need to write multiple images. But as in this demo you ve shown that only one image you are writing. currently i am looping that and writing to word but word document is blank and nothing is there. i have added modified code in the question . – Chandan Kumar Nov 07 '14 at 04:13
  • Image returnImage = Image.FromStream(ms); - Parameter invalid exception is appearing here. – Chandan Kumar Nov 07 '14 at 13:33
  • Thanks Jeremy. Will be waiting for the solution. – Chandan Kumar Nov 07 '14 at 13:46
  • See my edit that demo's inserting more than one picture and demo's how to use the `Paragraph` Object with `InsertParagraphAfter();`, also note how I finish the text in `oPara3` with a `Environment.Newline`. – Jeremy Thompson Nov 09 '14 at 00:58
  • Great, I am glad you have it working! Let me know if you have any other issues with this code (here in the comments). If you could award me the bounty it would be much appreciated, cheers :) – Jeremy Thompson Nov 10 '14 at 08:56