0

I try to save range of cells from excel file to a picture. I used the CopyPicture method from the interop.excel api so the picture sould be on clipboard. When i press ctrl+v on a word document for example, i get the picture but i can't success to get it with code. The returned data from the GetImageFromClipBoard method is null.

    public void SaveAsImage()
    {
        var usedRange = ws.UsedRange;
        int startRow = usedRange.Row;
        int endRow = startRow + usedRange.Rows.Count - 1;
        int startColumn = usedRange.Column;
        int endColumn = startColumn + usedRange.Columns.Count - 1; 
        Xl.Range rng = wb.ActiveSheet.Range[ws.Cells[1, 1], 
        ws.Cells[endRow, endColumn]];
        rng.CopyPicture(Xl.XlPictureAppearance.xlScreen, 
        Xl.XlCopyPictureFormat.xlBitmap);

        Image image = GetImageFromClipBoard();
        image.Save("image.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
    }

    [STAThread]
    private Image GetImageFromClipBoard()
    {
        IDataObject clipboardData = Clipboard.GetDataObject();
        Exception threadEx = null;
        Thread staThread = new Thread(
            delegate ()
            {
                try
                {
                    clipboardData = Clipboard.GetDataObject();
                }

                catch (Exception ex)
                {
                    threadEx = ex;
                }
            });
        staThread.SetApartmentState(ApartmentState.STA);
        staThread.Start();
        staThread.Join();
        return (Bitmap)clipboardData.GetData(DataFormats.Bitmap);
    }
lio lrn
  • 31
  • 4

1 Answers1

0

What you are trying to do is retrieving a bitmap from the clipboard, as type "Bitmap". I'm not sure Office uses that type at all, though.

Note that the DataFormats are not an enum; they just refer to string IDs commonly used for clipboard content. This immediately implies that you can add custom ones. These custom ones are generally put on the clipboard as byte stream. This answer details the way to store and fetch those byte arrays on the clipboard.

One of the main ones that is used is DIB (basically, a BMP file without its specific file header), but Office specifically uses these:

  • "PNG+Office Art"
  • "JFIF+Office Art"
  • "GIF+Office Art"
  • "PNG"
  • "JFIF"
  • "GIF"

(I heard the "+Office Art" ones are also just images, but I haven't tried that out myself)

So yeah, if you try to fetch these, make a new MemoryStream with the bytes from the clipboard, and make a new Bitmap from the MemoryStream, you should be there. You basically try them until you got something that sticks, starting with the PNG ones.

I wrote a more detailed explanation with full code a while ago, which focused specifically on copying and retrieving PNG and DIB on the clipboard.

Nyerguds
  • 5,360
  • 1
  • 31
  • 63