2016-10-03 109 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