2017-08-02 40 views
0

我有一個使用C#NI DAQmx代碼生成的DataTable。我想把這個DataTable放在一個Excel文件中,當選中CheckBox時。 DAQmx代碼一次記錄此數據的「x」個樣本數。當這個數字很高時,程序很慢,但它仍然有效。我想一次錄製少量的樣本,然後將這些數據保存到Excel文件中。如何使用DataTable連接Excel文件?

在我當前的代碼,在Excel文件中的數據被不斷改寫。這是不可取的,因爲我需要所有記錄的數據。

目前當檢查箱中的數據將積極記錄,但它不會串連。我嘗試了很多搜索,併爲此探索了很多方法,但我還沒有完全適應任何需求。

相關代碼將包含在下面。任何幫助表示讚賞,謝謝。

注:數據並不一定是一個.xlsx文件。它可以是一個.csv

此代碼是通過DAQmx的數據表生成:

private void DataToDataTable(AnalogWaveform<double>[] sourceArray, ref DataTable dataTable) 
    { 
     // Iterate over channels 
     int currentLineIndex = 0; 
     string test = currentLineIndex.ToString(); 

     foreach (AnalogWaveform<double> waveform in sourceArray) 
     { 
      for (int sample = 0; sample < waveform.Samples.Count; ++sample) 
      { 
       if (sample == 50) 
        break; 

       dataTable.Rows[sample][currentLineIndex] = waveform.Samples[sample].Value; 
      } 
      currentLineIndex++;  
     } 
    } 

    public void InitializeDataTable(AIChannelCollection channelCollection, ref DataTable data) 
    { 
     int numOfChannels = channelCollection.Count; 
     data.Rows.Clear(); 
     data.Columns.Clear(); 
     dataColumn = new DataColumn[numOfChannels]; 
     int numOfRows = 50; 

     for (int currentChannelIndex = 0; currentChannelIndex < numOfChannels; currentChannelIndex++) 
     { 
      dataColumn[currentChannelIndex] = new DataColumn() 
      { 
       DataType = typeof(double), 
       ColumnName = channelCollection[currentChannelIndex].PhysicalName 
      }; 
     } 

     data.Columns.AddRange(dataColumn); 

     for (int currentDataIndex = 0; currentDataIndex < numOfRows ; currentDataIndex++) 
     { 
      object[] rowArr = new object[numOfChannels]; 
      data.Rows.Add(rowArr); 
     } 
    } 

這是我目前保存到一個Excel文件的方法:既然你提到它

 private void Excel_cap_CheckedChanged(object sender, EventArgs e) 
    { 

        int i = 0; 
     for (excel_cap.Checked = true; excel_cap.Checked == true; i ++) { 

      { 
       StringBuilder sb = new StringBuilder(); 

       IEnumerable<string> columnNames = dataTable.Columns.Cast<DataColumn>(). 
                Select(column => column.ColumnName); 
       sb.AppendLine(string.Join(",", columnNames)); 

       foreach (DataRow row in dataTable.Rows) 
       { 
        IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString()); 
        sb.AppendLine(string.Join(",", fields)); 
       } 

       File.AppendAllText(filename_box.Text, sb.ToString()); 

      } 
     } 
    } 

回答

0

不必是Excel,它可以是CSV,那麼你可以使用你的CSV代碼,但將File.WriteAllText行更改爲File.AppendAllText,它將追加文本而不是替換現有文件。如果文件不存在,將會創建文件AppendAllText

File.AppendAllText("test.csv", sb.ToString()); 
+0

這非常有幫助。但是,你可以看看我編輯我當前的代碼嗎?我在你的改變中添加了它,它會在複選框更改後附加文件。只要'excel_cap.Checked = true',我就希望文件不斷地附加新信息。我知道這是一個業餘問題,但任何想法我可以解決這個問題? –

+0

@ScottMyers - 我看過代碼,我想我會遵循你的新問題,但在SO上,如果你需要另一部分/第二個問題的幫助,你需要發佈一個新問題。爲了幫助你指出正確的方向,這聽起來像你有生產者/消費者類型的問題。您應該考慮可能正在研究ConcurrentQueue,並且可能會保持文件的打開狀態,並在隊列中有數據時添加,但不知道更多關於此問題的信息,但很難給出答案。 – pstrjds

+0

啊,好的,謝謝。對不起菜鳥的錯誤。我感謝你的幫助! –

0

您確定您使用的是EPPlus嗎?這CreateExcelFile看起來像是a copied code snippet

隨着EPPlus,這將是那麼容易,因爲

using (var package = new ExcelPackage(new FileInfo(@"a.xslx"))) 
{ 
    if (!package.Workbook.Worksheets.Any()) 
     package.Workbook.Worksheets.Add("sheet"); 
    var sheet = package.Workbook.Worksheets.First(); 
    var appendRow = (sheet.Dimension?.Rows ?? 0) + 1; 
    sheet.Cells[appendRow, 1].LoadFromDataTable(new DataTable(), false); 
    package.SaveAs(new FileInfo(@"a.xslx")); 
} 

它看起來像你有一些對象,然後將其轉換爲DataTable,然後將它們寫入到Excel/CSV。如果你跳過到DataTable的轉換,你會加快速度。 EPPlus有LoadFromCollection,它可能只與AnalogWaveform<double>一起使用。

無恥的廣告:我這些片段從我blog post about EPPlus

+0

我可能可以更好地標記這個。你是對的,那是代碼片段的來源。我原本打算使用EPPlus,但無法適應它。我在'LoadFromDataTable'部分的代碼中出現錯誤。它表示'方法沒有超載'和'有1個參數'。任何想法爲什麼?另外,這將工作與兩列數據? –

+0

錯過第二個參數:'bool PrintHeaders' – Laoujin

+0

現在,該行('var appendRow = sheet.Dimension.Rows + 1;')正在拋出一個('NullReferenceException')錯誤。特別是('OfficeOpenXml.ExcelWorksheet.Dimension.get返回null')你知道如何解決這個問題嗎? –