Question

I've written the following simple C# console application to export all the charts from an Excel Workbook. It works just fine unless the chart has not been scrolled to since opening the document, in which case an empty image file is generated.

using Excel = Microsoft.Office.Interop.Excel;
using System;
using System.Diagnostics;

namespace ExcelExporter
{
    class ChartExporter
    {
        const string EXPORT_TO_DIRECTORY = @"C:\Users\Sandy\Desktop\Excel\Charts";

        static void Main(string[] args)
        {
            Excel.Application app = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application") as Microsoft.Office.Interop.Excel.Application;

            ConsoleColor c = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write("Export To: ");
            Console.ForegroundColor = c;
            string exportPath = Console.ReadLine();

            if (exportPath == "")
                exportPath = EXPORT_TO_DIRECTORY;

            Excel.Workbook wb = app.ActiveWorkbook;

            foreach (Excel.Worksheet ws in wb.Worksheets)
            {
                Excel.ChartObjects chartObjects = (Excel.ChartObjects)(ws.ChartObjects(Type.Missing));

                foreach (Excel.ChartObject co in chartObjects)
                {
                    Excel.Chart chart = (Excel.Chart)co.Chart;
//                  app.Goto(co, true);
                    chart.Export(exportPath + @"\" + chart.Name + ".png", "PNG", false);
                }
            }

            Process.Start(exportPath);
        }
    }
}

I've made a few failed attempts to scroll to the object; the commented out line towards the bottom of the program (app.Goto(co, true);) for example only works for ranges. Is there any way to scroll to ChartObjects, or otherwise ensure that they properly export to images?

For testing, use a workbook with charts 1000+ rows down (far enough that they are unquestionably out of view when the document opens); close and reopen the document before running the program (once scrolled to, the charts will have already been rendered and stored in memory).

Was it helpful?

Solution

VBA, but same idea would likely work for C#...

Dim co As ChartObject, sht As Worksheet, x As Long
x = 1
Set sht = ThisWorkbook.Sheets("Sheet1")
For Each co In sht.ChartObjects
    Application.Goto co.TopLeftCell, True
    co.Chart.Export "C:\_stuff\test\chart" & x & ".jpg", "JPG", False
    x = x + 1
Next co

OTHER TIPS

I found the following worked for me

            foreach (Excel.ChartObject co in chartObjects)
            {
                co.Select();
                Excel.Chart chart = (Excel.Chart)co.Chart;
                chart.Export(exportPath + @"\" + chart.Name + ".png", "PNG", false);
            }

.NET Core 3.1 using Interop.Excel and changing the COM ref in VS to Copy Local

   private static void ExportExcelChart()
    {
        var excelApp = new excel.Application(); 
        var wb = excelApp.Workbooks.Open(@"z:\scratch\acme_inc.xlsx");
        var ws = (excel.Worksheet)wb.Sheets[1];
        var chartObjects= ws.ChartObjects() as IEnumerable;

        foreach (excel.ChartObject co in chartObjects)
        { 
            co.Select();
            excel.Chart chart = (excel.Chart)co.Chart;
            chart.Export($@"z:\{chart.Name}.png", "PNG", false);
        }
        wb.Close();
        excelApp.Quit();
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top