2016-10-03 113 views
0

我的程序应该将某个Excel文件从一个文件夹中作为图像(SVG格式)导出到另一个文件夹中。这可以通过方法CopyAndSaveTo和ExportRangeAsImage完成,他们完成他们的工作。 在MainWindow上,我有一个按钮,单击它时会执行这两个功能。我希望点击这个按钮的用户被告知(Progressbar)这个过程有多远(复制+导出)。 我试图用一个BackgroundWorker来实现它,如果我的评论下面的代码(在方法ExportRangeAsImage)它只能:使用backgroundworker更新progressbar + clipboard.getimage() - WPF C#

Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage()); 
image.Save(ImagePath + Path.GetFileNameWithoutExtension(file) + ".svg"); 

否则我收到以下错误消息( 德国翻译):

在System.NullReferenceException中,发生了类型为“System.Drawing.dll”的异常,但未在用户代码中处理该异常。 附加信息:未将对象引用设置为对象实例。 如果处理程序可用于此异常,程序可能会继续安全运行。

这里是整个代码:

private void UpdateDataOfLine1(object sender, ExecutedRoutedEventArgs e) 
     { 
      string[] files = Directory.GetFiles(RootPath); 
  
      BackgroundWorker worker = new BackgroundWorker(); 
      worker.WorkerReportsProgress = true; 
      worker.DoWork += worker_DoWork; 
      worker.ProgressChanged += worker_ProgressChanged; 
      worker.RunWorkerAsync(); 
     } 
  

  
     void worker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      string[] files = Directory.GetFiles(RootPath); 
  
      for (int i = 0; i < files.Length; i++) 
      { 
       if (files[i].Contains("$") || files[i].Contains("~") || files[i].Contains("Thumb")) 
       { 
        continue; 
       } 
  
       File.Copy(files[i], DestPath + Path.GetFileName(files[i]), true); 
  
       string newFile = DestPath + Path.GetFileName(files[i]); 
  
       ExPortRangeAsImage(newFile); 
  
       (sender as BackgroundWorker).ReportProgress(i); 
       Thread.Sleep(100); 
      } 
     } 
  

  
     void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      Status.Value = e.ProgressPercentage; 
     } 
  

     public void ExPortRangeAsImage(string file) 
     { 
      var ExcelApp = new Microsoft.Office.Interop.Excel.Application(); 
  
      try 
      { 
       if (file.Contains("BeispielDatei")) 
       { 
        Workbook wb = ExcelApp.Workbooks.Open(file); 
        Worksheet ws = (Worksheet)wb.Sheets[1]; 
        Range range = ws.Range["A1:U35"]; 
        range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap); 
        wb.Close(SaveChanges: false); 
        Marshal.ReleaseComObject(wb); 
       } 
  
       else 
       { 
        Workbook wb = ExcelApp.Workbooks.Open(file); 
        Worksheet ws = (Worksheet)wb.Sheets[1]; 
        Range range = ws.Range["A1:U35"]; 
        range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap); 
        wb.Close(SaveChanges: false); 
        Marshal.ReleaseComObject(wb); 
       } 
      } 
  
      finally 
      { 
       Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage()); 
       image.Save(ImagePath + Path.GetFileNameWithoutExtension(file) + ".svg"); 
  
       Marshal.ReleaseComObject(ExcelApp); 
      } 
     } 

你能告诉我,我做错了什么或如何能实现呢? 除BackgroundWorker之外还有其他方法吗?

非常感谢您的帮助!

以下是错误

+0

当System.NullReferenceException和我们不知道除了什么代码时,可以设置stop。 – lindexi

+0

我添加了错误的屏幕截图... – Guilian

+0

检查这两行中的图像对象或ImagePath是否为空? – AnjumSKhan

回答

0

,应先查看堆栈跟踪的截图,我觉得你的内部异常很可能是由于跨线程访问冲突。

由于:System.Windows.Forms.Clipboard.GetImage()可能会返回null,因此可能会引发空引用。

你可以尝试运行在UI线程调度此部分:

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=> 
{ 
    Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage()); 
    image.Save(ImagePath + Path.GetFileNameWithoutExtension(file) + ".svg"); 
} 

这也将最有可能引入(复制和粘贴之间的比赛)的同步问题。您可能必须重构代码,以确保在将其他图像复制到剪贴板之前完成图像写入。

+0

感谢它与您的代码功能:) !!! – Guilian

+0

当任务在后台时,任务可以使用'System.Windows.Forms.Clipboard'吗? @loopedcode – lindexi

+0

它可以但它必须使用UI同步上下文。在此处查看示例:https://blogs.msdn.microsoft.com/csharpfaq/2010/06/18/parallel-programming-task-schedulers-and-synchronization-context/ – loopedcode