2017-02-07 3 views
0

多くを検索して、自分のニーズに適応できるものを見つけることができなかったので、私は尋ねようとしました。 基本的には、私の全範囲(usedRange) を通過するループがあり、同じ行に3列以上の列が空白(例A10、B10、C10)の場合は、行全体を削除する必要があります。私の試みのCを使用して3つ以上のExcel範囲でforeachループを作成する方法

一つ次のように:

xl.Range emptyCellsDel = MySheet.UsedRange.SpecialCells(xl.XlCellType.xlCellTypeBlanks); 
     xl.Range myRange = emptyCellsDel.Range["A:C"]; 
     const int aCol = 1; const int bCol = 2; const int cCol = 3; 
     for (int i = 1; i < MySheet.UsedRange.Rows.Count; i++) 
     { 
      if ((MySheet.Cells[i, aCol].Value ?? "").ToString() == "" && 
       (MySheet.Cells[i, bCol].Value ?? "").ToString() == "" && 
       (MySheet.Cells[i, cCol].Value ?? "").ToString() == "") 
      { 
       myRange.EntireRow.Delete(); 
      } 
     } 

アイディア/提案の任意の並べ替えは大歓迎素晴らしいと多くのだろう。 ありがとうございます!

答えて

0

forループによってアクセスされる範囲を変更しないように、削除する行をメモしてforループの外に削除する必要があります。

また、行をシフトさせる場合は、最後の行を最初に削除する必要があります。そのため、行インデックスが乱れることはありません。以下の例では、forループの順序を逆にし、行番号をリストに格納して順序付けを行うことでこれを行っています。

xl.Range myRange = emptyCellsDel.Range["A:C"]; 
const int aCol = 1; const int bCol = 2; const int cCol = 3; 
List<int> rowsToDelete = new List<int>(); 
int rowCount = MySheet.UsedRange.Rows.Count 
for (int i = rowCount; i >= 1; i--) 
{ 
    if ((MySheet.Cells[i, aCol].Value2 ?? "").ToString() == "" && 
     (MySheet.Cells[i, bCol].Value2 ?? "").ToString() == "" && 
     (MySheet.Cells[i, cCol].Value2 ?? "").ToString() == "") 
    { 
     rowsToDelete.Add(i); 
    } 
} 
foreach (int row in rowsToDelete) { ((Range)(MySheet.Rows[row])).Delete(XlDirection.xlUp); } 
+0

私はそれを試しましたが、何らかの理由で空の行が削除されません。 –

+0

.Valueを.Value2に切り替えてみてください。セルには、空白の既定値を持つ型を返すような(日付/時刻などの)書式設定がいくつかあります。 – SMStroble

+0

@JohnGあなたの権利を盗む。私はその変更をしたことを誓う、私はそれが私の答えにそれをしなかったと思う。一定。 – SMStroble

0

SmStrobleの回答が示すとおり、これまでにも言及しました。 ExcelファイルのTOPから空の行を削除すると、行を削除して他の行を上に移動すると索引付けの問題が発生し、ループ内の行の索引付けがスローされます。 forループコードでは、その変数はiです。この方法を使用すると、空の行が欠落し、空でない行が削除される可能性があります。

SmStrobleの答えがこの問題を解決する正しい方法ですが、いくつか問題があります。まず最初にコメントしたように、下から上に行を削除したいので、SmStrobleの解決策は、行をループして空の行の行インデックスを見つけ、List<int>に配置することです。ここでの唯一の問題は、ここでforeachループを使用すると、最後のリストではなくリストに置かれた最初のアイテムから開始されることです。

2番目の問題は実行時間です。 Excelの行をループすることはコストがかかることがあります。あなたはforループの中で、次のMySheet.UsedRangeラインを使用する場合:

for (int i = 1; i < MySheet.UsedRange.Rows.Count; i++) {… 

この行は高価です。シートに多数の行がある場合、これにはかなりの時間がかかります。このため、他のソリューションがあります。しかし、簡単な解決策は、単純に行数を保持し、以下のようなforループ内でそれを使用するint変数を作ることです。

int totalRows = MySheet.UsedRange.Rows.Count; 
for (int i = 1; i < totalRows; i++) { 

この小さな変更は大きく依存して実行を高速化しますスプレッドシートの行数。 730 +行のテストシートを使用すると、forループではUsedRangeforループ外のときは1118ミリ秒で2447ミリ秒かかりました。お役に立てれば。

string filePath = @"C:\YourPathToExcelFile\YourExcelFile.xls"; 
    Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application(); 
    ExcelApp.Visible = true; 
    Workbooks wbs = ExcelApp.Workbooks; 
    Workbook xlWorkbook = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false); 
    Excel._Worksheet MySheet = xlWorkbook.Sheets[1]; 
    const int aCol = 1; 
    const int bCol = 2; 
    const int cCol = 3; 
    List<int> rowsToDelete = new List<int>(); 
    int totalRows = MySheet.UsedRange.Rows.Count; 
    for (int i = totalRows; i > 0; i--) { 
    if ((MySheet.Cells[i, aCol].Value ?? "").ToString() == "" && 
     (MySheet.Cells[i, bCol].Value ?? "").ToString() == "" && 
     (MySheet.Cells[i, cCol].Value ?? "").ToString() == "") { 
     rowsToDelete.Add(i); 
    } 
    } 

    foreach (int row in rowsToDelete) { 
    ((Range)(MySheet.Rows[row])).Delete(XlDirection.xlUp); 
    } 

    xlWorkbook.Save(); 
    xlWorkbook.Close(); 
    ExcelApp.Quit(); 
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbook); 
    System.Runtime.InteropServices.Marshal.ReleaseComObject(ExcelApp); 

    Console.WriteLine("Fished processing! Press any key to exit"); 
    Console.ReadKey(); 

EDIT:トップにExcelファイルの底部からループに上記のコードを変更しました。これにより、rowsToDeleteのリストを元に戻す必要がなくなります。

+0

私はこれも同様に試しましたが、動作させることができません。 私はここで何か間違っていると確信していますが、私はそれを動作させることができるまでそれを試してみようと思います。 通常動作するExcelファイルは、およそ20,000〜30,000行あります。 私はこの作業をこれまでのところ行ってきましたが(私はそれをもう少し贅沢にしようとしました)、私の最初の列にはfilterinがあり、時には2列目と3列目に空白があるかもしれないことを知り、空白の行を取得して削除します。しかし、私はそれについて少し「もっと大きくて良い」と思っていました。 私はa.s.a.p.を更新します。ありがとうございました ! –

関連する問題