如何将Excel工作表导出为图片?

3
我将尝试从Excel工作表生成图片。经过大量的研究,我正在使用以下代码,但在某个点上我遇到了异常:
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();                
            }

        }
    }
}

我正在使用Office 2013,64位,Windows 7 64位和.Net 4.5。


你收到了什么异常,出现在哪一行? - Tim Williams
在带有注释的那一行下面,我理解了注释所说的内容。 - Daniel San
为什么不直接从剪贴板导出图像呢?http://social.msdn.microsoft.com/Forums/vstudio/en-US/9c2a05de-c680-4515-898a-e92f28eddbf9/retrieve-image-from-clipboard-and-save-it-in-different-formats - Tim Williams
好主意。我已经尝试过了,问题是即使我可以将其粘贴到MS Paint中,但Clipboard.GetDataObject()没有返回任何内容。 - Daniel San
4个回答

3

这对我在WinForms项目中有效:

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();
        }



    }
}

对于控制台应用程序,您还需要查看:http://blog.another-d-mention.ro/programming/c/use-clipboard-copypaste-in-c-console-application/

(此文讲述如何在 C 语言控制台应用程序中使用剪贴板复制和粘贴)

你的答案没问题。但是出现了异常情况。我已经开了一个新的问题来解决这个问题:http://stackoverflow.com/questions/21850999/how-can-i-avoid-this-exception-when-copying-a-selected-range-in-excel - Daniel San
请注意,您不需要使用剪贴板 -- 您可以将工作簿转换为IDataObject,并获取所选工作表的位图格式。此外,Jpeg不是Excel屏幕截图的最佳选择(该格式针对摄影进行了优化,对于此类用途,Jpeg会引入视觉伪影)-- 最好将图像编码为PNG格式。 - BrainSlugs83
1
我尝试在我的控制台应用程序中使用您的代码,但 "Clipboard.GetDataObject()" 得到了空值。你能给我一些建议吗? - Sugar

3

无需创建Chart对象。在Range上调用CopyPicture()将图像放置在系统剪贴板上。如果您想要,您可以在仅两个步骤中完成它:

        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(); */

编辑:所有的错误检查和流程控制都由你来处理,但是当然明智的做法是在尝试访问剪贴板内容之前(至少)使用Clipboard类的ContainsImage()方法。


与上述评论相同--无需覆盖剪贴板--只需将Workbook对象直接转换为IDataObject即可--这样可以正常工作。 - BrainSlugs83

1
可能在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

我可以单独使用VBA吗?我问这个问题是因为我需要做更多的事情,比如查询数据库和其他操作。 - Daniel San
一个很好的问题!也许可以修改脚本以在工作簿之外运行......我会开一个新帖子来问这个问题..... - Gary's Student

0
                    //station--> excel file path
                    var app = new Microsoft.Office.Interop.Excel.Application();
                    var xls = app.Workbooks.Open(Station,false,true);
                    Microsoft.Office.Interop.Excel.Sheets sheets = xls.Worksheets;
                    for (int j = 1; j <= sheets.Count; j++)
                    {
                        Microsoft.Office.Interop.Excel.Worksheet sheet = sheets[j];
                        string startRange = "A1";
                        Microsoft.Office.Interop.Excel.Range endRange = sheet.Cells.SpecialCells(Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
                        Microsoft.Office.Interop.Excel.Range range = sheet.get_Range(startRange, endRange);
                        range.Rows.AutoFit();
                        range.Columns.AutoFit();
                        range.Copy();

                        BitmapSource image = Clipboard.GetImage();
                        FormatConvertedBitmap fcbitmap = new FormatConvertedBitmap(image, PixelFormats.Bgr32, null, 0);
                        using (var fileStream = new FileStream(AppDomain.CurrentDomain.BaseDirectory + j + ".jpg", FileMode.Create))
                        {
                            PngBitmapEncoder encoder = new PngBitmapEncoder();
                            encoder.Interlace = PngInterlaceOption.On;
                            encoder.Frames.Add(BitmapFrame.Create(fcbitmap));
                            encoder.Save(fileStream);
                        }
                        Set_Cavnas(AppDomain.CurrentDomain.BaseDirectory  +j + ".jpg");
                        File.Delete(AppDomain.CurrentDomain.BaseDirectory  +j + ".jpg");
                    }
                    //release resources
                    app.DisplayAlerts = false;
                    xls.Close(false);
                    app.Quit();
                    GC.Collect();

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接