How can I export an excel worksheet as image?

4

I'm triying to generate an image from an excel worksheet. After a lot of research, I'm using the following code, but at some point I get an exception:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Excel;

namespace ConsoleApplication1
{
    class Prueba
    {
        [STAThread]
        static void Main(string[] args)
        {
            var a = new Microsoft.Office.Interop.Excel.Application();

            try
            {
                Workbook w = a.Workbooks.Open(@"C:\SCRATCH\Libro2.xlsx");
                Worksheet ws = w.Sheets["Report"];
                ws.Protect(Contents: false);
                Range r = ws.Range["B2:H20"];
                r.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
                a.DisplayAlerts = false;

                // System.Runtime.InteropServices.COMException Excepción de HRESULT: 0x80010105 (RPC_E_SERVERFAULT)
                ChartObject chartObj = ws.ChartObjects().Add(r.Left, r.Top, r.Width, r.Height); 

                chartObj.Activate();
                Chart chart = chartObj.Chart;
                chart.Paste();
                chart.Export(@"C:\SCRATCH\image.JPG", "JPG");
                chartObj.Delete();
                w.Close(SaveChanges: false);
            } 
            finally
            {
                a.Quit();                
            }

        }
    }
}

I'm using Office 2013, 64 bits, Windows 7 64 and .Net 4.5.

c#
excel
asked on Stack Overflow Feb 13, 2014 by Daniel San

3 Answers

3

This worked for me in a WinForms project:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using ios = System.Runtime.InteropServices;

namespace ClipBoardTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void ExportRangeAsJpg()
        {
            Excel.Application xl;

            xl = (Excel.Application)ios.Marshal.GetActiveObject("Excel.Application");

            if (xl == null)
            {
                MessageBox.Show("No Excel !!");
                return;
            }

            Excel.Workbook wb = xl.ActiveWorkbook;
            Excel.Range r = wb.ActiveSheet.Range["A1:E10"];
            r.CopyPicture(Excel.XlPictureAppearance.xlScreen,
                           Excel.XlCopyPictureFormat.xlBitmap);

             if (Clipboard.GetDataObject() != null)
            {
                IDataObject data = Clipboard.GetDataObject();

                if (data.GetDataPresent(DataFormats.Bitmap))
                {
                    Image image = (Image)data.GetData(DataFormats.Bitmap, true);
                    this.pict1.Image = image;
                    image.Save(@"C:\_Stuff\test\sample.jpg",
                        System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                else
                {
                    MessageBox.Show("No image in Clipboard !!");
                }
            }
            else
            {
                MessageBox.Show("Clipboard Empty !!");
            }  
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ExportRangeAsJpg();
        }



    }
}

For a console app you need to see also: http://blog.another-d-mention.ro/programming/c/use-clipboard-copypaste-in-c-console-application/

answered on Stack Overflow Feb 14, 2014 by Tim Williams
2

No need to create a Chart object. Calling CopyPicture() on the Range puts the image on the system clipboard. You can finish it off in as little as two steps, if you want:

        Workbook w = a.Workbooks.Open(@"C:\SCRATCH\Libro2.xlsx");
        Worksheet ws = w.Sheets["Report"];
        ws.Protect(Contents: false);
        Range r = ws.Range["B2:H20"];
        r.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);

        Bitmap image = new Bitmap(Clipboard.GetImage());
        image.Save(@"C:\SCRATCH\image.png");

        // charting code, replaced with the above 
               /* ChartObject chartObj = ws.ChartObjects().Add(r.Left, r.Top, r.Width, r.Height); 

                chartObj.Activate();
                Chart chart = chartObj.Chart;
                chart.Paste();
                chart.Export(@"C:\SCRATCH\image.JPG", "JPG");
                chartObj.Delete(); */

EDIT: Leaving all the error checking and flow control to you, but it would be wise of course to (at least) use the ContainsImage() method of the Clipboard class before trying to access it's content.

answered on Stack Overflow Feb 14, 2014 by B L • edited Feb 14, 2014 by B L
1

Might be easier in VBA :

Sub PictureSaver()
    Dim ch As Chart
    Charts.Add
    Set ch = ActiveChart
    Sheets("Sheet4").Select
    Range("A1:D4").Select
    Selection.CopyPicture Appearance:=xlScreen, Format:=xlPicture
    ch.Select
    ch.Paste
    ch.Export Filename:="sample.jpg"
    Application.DisplayAlerts = False
        ch.Delete
    Application.DisplayAlerts = True
End Sub
answered on Stack Overflow Feb 13, 2014 by Gary's Student

User contributions licensed under CC BY-SA 3.0