2016-10-06 55 views
0

在我的帖子'How to export DateTime, TimeSpan, string and double values to Excel from WPF MVVM application?'中,我询问了如何使用VSTO从WPF MVVM应用程序中导出MS Excel。不等待答案,我决定尝试自己去做。我的电脑上有'MS Excel 2016 MSO(16.0.4432.1000)64-bit版本'。我一直在写下面的代码来实现导出。Excel._Worksheet中的单元格未正确填充数据

// Exports to MS Excel. 
    private async void exportToExcel() 
    { 
     await Task.Run(() => 
     { 
      // Cell index. 
      int cellIndex = 2; 
      // MS Excel application instance. 
      Excel.Application oXL = null; 
      // Work book. 
      Excel._Workbook oWB; 
      // Active work sheet. 
      Excel._Worksheet oSheet; 
      // Cell range. 
      Excel.Range oRng; 
      // Next sheet index. 
      int sheetIndex = 2; 

      try 
      { 
       //Start Excel and get Application object. 
       oXL = new Excel.Application(); 
       oXL.Visible = false; 
       //Get a new workbook. 
       oWB = oXL.Workbooks.Add(Missing.Value); 
       // Get shets quantity. 
       int sheetsQuantity = oWB.Sheets.Count; 
       // Get active sheet. 
       oSheet = (Excel._Worksheet)oWB.ActiveSheet; 

       //Add table headers going cell by cell. 
       oSheet.Cells[1, 1] = "Date"; 
       oSheet.Cells[1, 2] = "Time"; 
       oSheet.Cells[1, 3] = "Beam"; 
       oSheet.Cells[1, 4] = "Direction"; 
       oSheet.Cells[1, 5] = "Value"; 
       //Format A1:E1 as bold, vertical alignment = center. 
       oSheet.get_Range("A1", "E1").Font.Bold = true; 
       oSheet.get_Range("A1", "E1").VerticalAlignment = Excel.XlVAlign.xlVAlignCenter; 

       // Get name of file to export to Excel. 
       string fileDateTime = DateTime.Now.ToString("dd.mm.yyyy hh:mm:ss"); 
       fileDateTime = fileDateTime.Replace(".", ""); 
       fileDateTime = fileDateTime.Replace(":", ""); 
       fileDateTime = fileDateTime.Replace(' ', '_'); 
       string fileName = "test_" + fileDateTime + ".xlsx"; 

       // Exporting in Excel. 
       while (this._isAbsoluteChartDataBeingExported) 
       { 
        AGC_DataRecordToSave record; 
        if (this._agcAbsoluteDataRecordsToSaveBuf.TryDequeue(out record)) 
        { 
         try 
         { 
          oSheet.Range["A" + cellIndex].Value = record.Date.ToString("d"); 
          oSheet.Range["B" + cellIndex].Value = record.Time.ToString("T"); 
          oSheet.Range["C" + cellIndex].Value = record.MeasuringBeam.ToString(); 
          oSheet.Range["D" + cellIndex].Value = record.Direction; 
          oSheet.Range["E" + cellIndex].Value = record.Value; 
         } 
         catch(COMException) 
         { 
          //AutoFit columns A:E. 
          oRng = oSheet.get_Range("A1", "E1"); 
          oRng.EntireColumn.AutoFit(); 

          // If sheets number more than one. 
          if (sheetsQuantity > 1) 
          { 
           // If next sheet index is less than quantity of sheets then get next sheet and activate it. 
           if (sheetIndex < sheetsQuantity) 
           { 
            oSheet = oWB.Sheets[sheetIndex]; 
            oSheet.Activate(); 
            sheetIndex += 1; 

            cellIndex = 2; 
            //Add table headers going cell by cell. 
            oSheet.Cells[1, 1] = "Date"; 
            oSheet.Cells[1, 2] = "Time"; 
            oSheet.Cells[1, 3] = "Beam"; 
            oSheet.Cells[1, 4] = "Direction"; 
            oSheet.Cells[1, 5] = "Value"; 
            //Format A1:E1 as bold, vertical alignment = center. 
            oSheet.get_Range("A1", "E1").Font.Bold = true; 
            oSheet.get_Range("A1", "E1").VerticalAlignment = Excel.XlVAlign.xlVAlignCenter; 
            continue; 
           } 
           else 
           { 
            // Else, add new sheet in workbook. 
            oWB.Sheets.Add(Missing.Value, oSheet, 1, Excel.XlSheetType.xlWorksheet); 
            oSheet = oWB.Sheets[2]; 
            oSheet.Visible = Excel.XlSheetVisibility.xlSheetHidden; 
            sheetsQuantity += 1; 
            sheetIndex += 1; 

            cellIndex = 2; 
            //Add table headers going cell by cell. 
            oSheet.Cells[1, 1] = "Date"; 
            oSheet.Cells[1, 2] = "Time"; 
            oSheet.Cells[1, 3] = "Beam"; 
            oSheet.Cells[1, 4] = "Direction"; 
            oSheet.Cells[1, 5] = "Value"; 
            //Format A1:E1 as bold, vertical alignment = center. 
            oSheet.get_Range("A1", "E1").Font.Bold = true; 
            oSheet.get_Range("A1", "E1").VerticalAlignment = Excel.XlVAlign.xlVAlignCenter; 
            continue; 
           } 
          } 
          else 
          { 
           // Else, add new sheet in workbook. 
           oWB.Sheets.Add(Missing.Value, oSheet, 1, Excel.XlSheetType.xlWorksheet); 
           oSheet = oWB.Sheets[2]; 
           oSheet.Visible = Excel.XlSheetVisibility.xlSheetHidden; 
           sheetsQuantity += 1; 
           sheetIndex += 1; 

           cellIndex = 2; 
           //Add table headers going cell by cell. 
           oSheet.Cells[1, 1] = "Date"; 
           oSheet.Cells[1, 2] = "Time"; 
           oSheet.Cells[1, 3] = "Beam"; 
           oSheet.Cells[1, 4] = "Direction"; 
           oSheet.Cells[1, 5] = "Value"; 
           //Format A1:E1 as bold, vertical alignment = center. 
           oSheet.get_Range("A1", "E1").Font.Bold = true; 
           oSheet.get_Range("A1", "E1").VerticalAlignment = Excel.XlVAlign.xlVAlignCenter; 
           continue; 
          } 
         } 
        } 
        cellIndex++; 
       } 

       // Save work book in XLSX-file. 
       if (!File.Exists(Path.Combine(this.PathToCsvRepository, fileName))) 
        oWB.SaveAs(Path.Combine(this.PathToCsvRepository, fileName), Missing.Value, Missing.Value, Missing.Value, true, true, Excel.XlSaveAsAccessMode.xlNoChange, 
         Excel.XlSaveConflictResolution.xlLocalSessionChanges, Missing.Value, Missing.Value, Missing.Value, true); 
      } 
      catch (IOException ex) 
      { 
       string errorMessage = string.Empty; 
       errorMessage = string.Concat(errorMessage, ex.Message); 
       errorMessage = string.Concat(errorMessage, " Line: "); 
       errorMessage = string.Concat(errorMessage, ex.Source); 
       MessageBox.Show(errorMessage, "Ошибка"); 
      } 
      catch (Exception ex) 
      { 
       string errorMessage = string.Empty; 
       errorMessage = string.Concat(errorMessage, ex.Message); 
       errorMessage = string.Concat(errorMessage, " Line: "); 
       errorMessage = string.Concat(errorMessage, ex.Source); 
       MessageBox.Show(errorMessage, "Ошибка"); 
      } 
      finally 
      { 
       // Complete work with Excel. 
       CloseExcel(oXL); 
      } 
     }); 
    } 

哪里_agcAbsoluteDataRecordsToSaveBuf是ConcurrentQueue实例,_isAbsoluteChartDataBeingExported是当用户打开出口到MS Excel和取消当用户关闭该出口设置的布尔标志。以下是用于关闭Excel中的方法:

// Closes Excel. 
    private static void CloseExcel(Excel.Application theApp) 
    { 
     int id = 0; 
     IntPtr intptr = new IntPtr(theApp.Hwnd); 
     System.Diagnostics.Process p = null; 
     try 
     { 
      GetWindowThreadProcessId(intptr, out id); 
      p = System.Diagnostics.Process.GetProcessById(id); 
      if (p != null) 
      { 
       p.Kill(); 
       p.Dispose(); 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("CloseExcel:" + ex.Message); 
     } 
    } 

我需要的是:1)创建在活动工作表中的标题和定义XLSX文件的名称。 2)在_isAbsoluteChartDataBeingExported == true时一直轮询ConcurrentQueue实例以获取现有数据。 3)从ConcurrentQueue实例中获取AGC_DataRecordToSave的当前实例(记录以导出)。 4)从AGC_DataRecordToSave实例中获取字段的值,并将这些字段值通过单元格的适当索引(cellIndex变量)赋予WorkSheet的单元格。 5)更正单元格的索引并再次轮询ConcurrentQueue实例以获取新记录。等等。如果当前活动工作表上的行数达到限制(抛出COMException),请转至下一张WorkBook(使此列表处于活动状态),然后重复2) - 5)项。等等。当用户将输出转换为MS Excel时,将WorkBook(带有数据的表格)写入XLSX文件。但我无法达到预期的效果。下面是在MS Excel中看到的结果。

enter image description here 而只有第一张有数据。所有剩余的纸张都是空的。然而,正如你所看到的,一张不均匀的枚举枚举已经存在(1,2,109,108,...)。但是纸张的数量必须如下(1,2,3,4,...)。我做错了什么?请帮助我纠正并消除错误,并使'exportToExcel'方法正常工作。

回答

1

有一个简单的方法来使用npoi.mapper只有2行以下。而且它不需要在服务器上安装MS Office。

var mapper = new Mapper(); 
mapper.Save("test.xlsx", objects, "newSheet"); 
+0

我收到你的赦免,DonnyTian,但我不问有关哪个库更好,我问我应该在我的代码中做什么以获得正确的结果。 – Prohor

相关问题