2

I made an AddIn for Excel (2016), that saves the print area as a jpg file. It worked fine for a few months. Nowadays I get more and more error reports from users, all get the same error (picture below). The users have Windows 7 with Excel 2013 or Windows 10 with Excel 2016, both have this error. At the first times reinstall of my program helped, but from now it doesn't help.

enter image description here

Here's my code:

public static void Save(string report, string area, RibbonControlEventArgs e)
{
    Excel.Window window = e.Control.Context;
    Excel.Worksheet sheet = ((Excel.Worksheet)window.Application.ActiveSheet);
    Excel.Range range = sheet.Range[sheet.PageSetup.PrintArea];

    range.CopyPicture(Excel.XlPictureAppearance.xlPrinter, Excel.XlCopyPictureFormat.xlPicture);
    range.Copy(Type.Missing);

    string fileName = @"\\server.company.lan\report.jpg";

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

        Image image = (Image)data.GetData(DataFormats.Bitmap, true);
        image.Save(fileName, ImageFormat.Jpeg);
    }
}
Adam Miklosi
  • 764
  • 5
  • 18
  • 28
  • 1
    Are you running that on a non-STA thread? (PS: the type of Exception could seriously help...) also check this: https://stackoverflow.com/questions/68666/clipbrd-e-cant-open-error-when-setting-the-clipboard-from-net – Simon Mourier Sep 06 '17 at 21:13
  • @SimonMourier Yes, I'm running that on a non-STA thread. I attached the error message to my question, that's all I have, due I can't reproduce this error on my computer. – Adam Miklosi Sep 07 '17 at 06:56
  • 1
    You must use an STA thread to access the clipboard. – Simon Mourier Sep 07 '17 at 07:11
  • @SimonMourier It works! Thank you for your help! – Adam Miklosi Sep 08 '17 at 08:06

1 Answers1

3

All clipboard access must run using an STA thread. There are many ways to do this:

  • use BeginInvoke functions (Winforms or WPF) that guarantee the code runs on the UI thread (which should be STA)
  • start your own Thread instance and use SetAparmentState(STA),
  • etc.
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298