2016-06-16 13 views
-1

У меня есть функция, которая закругляется на DataTable и сохраняет его в качестве Excel File с использованием SpreadSheetLight для C#переменная имеет значение, но бросает ссылка на объект не указывает на экземпляр объекта

заметив, что цикл по DataTable и для сохранения его результата Excel File требуется время, зависящее от того, сколько ячеек и строк и столбцов было у DataGrid, или там, где было извлечено DataTable.

перед использованием BackgroundWorker в моей функции функция выполняется должным образом. единственное оповещение без BackgroundWorker, конечно же, что пользовательский интерфейс зависает во время выполнения кодов. и, используя BackgroundWorker, я знаю, что могу устранить это, обработав функцию сохранения в другом потоке.

но после применения BackgroundWorker в моей функции, все сохраняет функция перерывы. он бросает мне Object Reference not set to an instance of an Object, но я отлаживал и отслеживал и убедился, что обе переданные переменные имеют значения в нем и не являются нулевыми. цикл, который я использовал, был таким же, как и раньше, и я даже попытался использовать For Loop.

вот фрагмент того, с чем я столкнулся. и, как вы можете видеть, окно ниже показывает, что переменная cell и value имеет в себе содержимое. но бросает мне нулевую ссылку.

enter image description here

кроме того, здесь полный код моей функции

 public void exportSingleDataGridToExcelFile(DataTable dt) { 
      using(var sfd = new SaveFileDialog()) { 
       sfd.FileName = string.Format("WIP Monitoring-{0}", DateTime.Now.ToString("MM.dd.yyyy")); 
       sfd.Filter = "Excel File (*.xlsx)|*.xlsx"; 

       if(sfd.ShowDialog() == DialogResult.OK) { 
        clb.Enabled = false; 
        cb.Enabled = false; 
        btn.Visible = false; 
        pb.Visible = true; 
        pb.Value = 50; 

        using(var excel = new SLDocument()) { 
         var style = excel.CreateStyle(); 
         style.SetHorizontalAlignment(DocumentFormat.OpenXml.Spreadsheet.HorizontalAlignmentValues.Center); 
         style.SetVerticalAlignment(DocumentFormat.OpenXml.Spreadsheet.VerticalAlignmentValues.Center); 

         var bgw = new BackgroundWorker(); 
         bgw.WorkerReportsProgress = true; 

         bgw.DoWork += (ss, ee) => { 
          var worker = ss as BackgroundWorker; 

          var count = (dt.Rows.Count + 1) * dt.Columns.Count; 
          var steps = (double) count/100; 
          var prog = 0.0; 
          var row = 0; 
          var col = 0; 

          //Get Column Headers 
          foreach(DataColumn dc in dt.Columns) { 
           var cell = string.Format("{0}1", col.getExCol()); 
           var value = dc.ColumnName; 

           excel.SetCellValue(cell, value); 
           excel.AutoFitColumn(string.Format("{0}1", col.getExCol())); 
           excel.SetCellStyle(string.Format("{0}1", col.getExCol()), style); 

           prog += steps; 
           worker.ReportProgress(((int) prog * 100)); 

           col++; 
          } 

          col = 0; 

          //Get Cell Data 
          foreach(DataRow dr in dt.Rows) { 
           foreach(DataColumn dc in dt.Columns) { 
            var cell = string.Format("{0}{1}", col.getExCol(), row); 
            var value = dr[dc].ToString(); 

            excel.SetCellValue(cell, value); 
            excel.AutoFitColumn(cell, row); 
            excel.SetCellStyle(cell, style); 

            prog += steps; 
            worker.ReportProgress(((int) prog * 100)); 

            col++; 
           } 
           col = 0; 
           row++; 
          } 
         }; 

         bgw.ProgressChanged += (ss, ee) => { 
          pb.Value = ee.ProgressPercentage/100; 
         }; 

         bgw.RunWorkerCompleted += (ss, ee) => { 
          try { 
           excel.SaveAs(sfd.FileName); 
           form.Close(); 
          } catch(Exception ex) { 
           MessageBox.Show(ex.Message, "Error while saving", MessageBoxButtons.OK, MessageBoxIcon.Error); 
          } 
         }; 

         bgw.RunWorkerAsync(); 
        } 
       } 
      } 
     } 

первоначально этот же код работал, прежде чем я реализовал свою BackgroundWorker.

В надежде, что я получу здесь какую-то прогулку.

+2

переменная 'excel' из инструкции' using' не передается в обработчик события 'bgw.DoWork' – Claies

+1

Очень хороший дисплей вопроса btw; красиво выложены с большой информацией. –

+0

@ Claies похоже. спасибо, что заметили это для меня – TheQuestioner

ответ

2

Очень вероятно, что что-то внутри экземпляра SLDocuemnt в excel является null, когда ваш фоновый рабочий выполнен.

Вы создаете excel в заявлении using. Это означает, что в конце блока using будет удален excel. Но внутри этого блока вы начинаете работника фона, который использует эту переменную .

Фоновый работник, безусловно, работает дольше, чем ваш блок using, поэтомууже настроен при попытке получить к нему доступ и выполнить строку, которая выдает исключение.

немедленное решение будет не использовать using здесь. Но, возможно, лучше создать экземпляр excel переменной внутри метод рабочего рабочего, так как вам все равно не нужно.

+0

мы подозреваем то же самое тоже. после публикации этого вопроса я попытался удалить блок using и объявить переменную 'excel' поверх функции. проблема исчезла, и я снова начал работать. Я думаю, что я оставлю этот вопрос здесь, если другие люди подумают о том же, что и я. спасибо – TheQuestioner

1

Я уверен, что ваша переменная excel является той, которая является Null при чтении исключения. Не значения в вызове метода.

Я подозреваю, что это связано с работой на заднем плане.

+0

я удалил using() {}; блок, и все прошло хорошо. Спасибо – TheQuestioner