2015-01-10 39 views
0

我正在閱讀使用.NET的excel,並需要對該excel執行某些檢查。 Excel的例子如下:一個特殊的循環查詢

ColumnA ColumnB ColumnC 

1001 Null 10 
1001 W101 5 
1001 W102 4 
1001 W103 2 

1002 Null 12 
1002 W104 5 
1002 W105 3 

1003 W106 5 
1003 W107 2 

要求如下:

如果在ColumnB一個Null條目,那麼我需要的值ColumnC下比較,即。這些值的總和(5,4,2與值W101,W102,W103)應該等於10(值對Null),如果不是,則在日誌文件中寫入錯誤。

My problem is that the there can be n values in ColumnC, how to loop against it. 

在上述出類拔萃,對應於1001(ColumnA)的值是4號,而對應於1002,1003(ColumnA)中的值數分別爲3和2。 如何爲它編寫通用邏輯,我無法理解。

下面是我寫的代碼,但只有在ColumnA中有4個對應於1001的值時才能使用。

FileStream file = File.Open(path, FileMode.Open, FileAccess.Read); 
IExcelDataReader obj = ExcelReaderFactory.CreateOpenXmlReader(file);//uses a 3rd party library 

obj.IsFirstRowAsColumnNames = true; 
DataSet ds = obj.AsDataSet(); 

DataTable dt = ds.Tables[0]; 
for (int i = 0; i < dt.Rows.Count; i++) 
{ 
    if (dt.Rows[i][1].ToString() == "Null") 
    { 
     double a = (double)dt.Rows[i][2]; 
     double x = (double)dt.Rows[i + 1][2]; 
     double y = (double)dt.Rows[i + 2][2]; 
     double z = (double)dt.Rows[i + 3][2]; 

     if (a != (x+ y + z)) 
     { 
      Response.Write("Mismatch in row: " + dt.Rows[i + 1][1]); 
      Response.Write("<br/>"); 
     } 
    } 
} 

而且,我已經使用了第三方庫來讀取Excel和其轉換成DataSet

回答

0

下面的查詢將得到的結果,你需要:使用

測試數據:

DataTable dt = new DataTable(); 

dt.Columns.Add(new DataColumn("A", typeof(string))); 
dt.Columns.Add(new DataColumn("B", typeof(string))); 
dt.Columns.Add(new DataColumn("C", typeof(int))); 

dt.Rows.Add(new object[] { "1001", "Null", 10 }); 
dt.Rows.Add(new object[] { "1001", "W101", 5 }); 
dt.Rows.Add(new object[] { "1001", "W102", 4 }); 
dt.Rows.Add(new object[] { "1001", "W103", 1 }); 

dt.Rows.Add(new object[] { "1002", "Null", 12 }); 
dt.Rows.Add(new object[] { "1002", "W104", 5 }); 
dt.Rows.Add(new object[] { "1002", "W105", 3 }); 

dt.Rows.Add(new object[] { "1003", "W106", 5 }); 
dt.Rows.Add(new object[] { "1003", "W107", 2 }); 

LINQ:

var result = 
    dt 
    .AsEnumerable() 
    // Group by the A-column. 
    .GroupBy(r => (string)r["A"]) 
    // Get only those groups where the first item in the B-column is 'Null': 
    .Where(g => g.FirstOrDefault(r => (string)r["B"] == "Null") != null) 
    // Get only those groups where the sum of the items of the C-column 
    // after the first one is different from the first item: 
    .Where(g => (int)g.First()["C"] != g.Skip(1).Sum(r => (int)r["C"])) 
    .ToList(); 

結果將包含由A柱細分電子郵件行時,有無效的金額。如果您對actaul行不感興趣,但只有在它們有效時纔會將.Any()代替.ToList()


如果不使用"Null"string不過是一個真正null像:

dt.Rows.Add(new object[] { "1001", null, 10 }); 

你需要更換第一Where到:

.Where(g => g.FirstOrDefault(r => r.Field<string>("B") == null) != null) 
+1

謝謝你回答。我會嘗試你的解決方案。 – Anurag

+0

我不確定'Null'是'string'還是_real_'null',所以我在這個例子中使用了字符串。你可能不得不在'FirstOrDefault'中將它改爲'null'來檢查它。 – t3chb0t

+0

它可能寫爲「空」或可能是空字符串。我會照顧的。 – Anurag