2017-02-07 14 views
0

После поиска многого и неспособного найти что-то, что я мог бы приспособить к моим потребностям, я решил, что попробую спросить. В принципе, мне нужен цикл, который прошел бы весь мой диапазон (usedRange) и проверял, если в той же строке ячейки из 3 или более столбцов пусты (пример A10, B10, C10), тогда вся строка должна быть удалена ,Как сделать цикл foreach с тремя или более диапазонами Excel с помощью C#

Один из моих попыток следующим образом:

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(); 
      } 
     } 

Любой вид Idea/предложение было бы удивительным и высоко ценится. Спасибо заранее!

ответ

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

Попробуйте переключиться. Значения .Value2 ячейки могут иметь некоторое форматирование (например, дату/время), которое возвращает тип с не пустым значением по умолчанию. – SMStroble

+0

@JohnG Дерьмо ваше право. Клянусь, я сделал это изменение, я думаю, это не повлияло на мой ответ. Исправлена. – SMStroble

0

Как указано в ответе SmStroble, и я упомянул ранее. Если вы запуститесь в TOP файла excel и удалите пустые строки, вы столкнетесь с проблемой индексирования при удалении строки и смещении других, индексирование строк в цикле будет сброшено. В коде цикла for вы указали эту переменную i. Использование этого подхода пропустит пустые строки и, возможно, удалит непустые строки.

Ответ SmStroble - это правильный способ исправить эту проблему, однако есть несколько проблем. Сначала, как мы прокомментировали, мы хотим удалить строки снизу вверх, поэтому решение SmStroble - это цикл строк, чтобы найти индексы строк для пустых строк и поместить их в List<int>. Единственная проблема здесь в том, что при использовании цикла foreach здесь он начинается с первого элемента, помещенного в список, а не из последнего.

Вторая проблема, с которой вы можете столкнуться, - это время выполнения. Цикл через строки Excel может быть дорогостоящим. При использовании следующей MySheet.UsedRange линии в for цикле:

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

Эта линия является дорогостоящим. Если на листе много строк, это может занять значительное количество времени. Есть и другие решения для этого, однако простое решение, чтобы просто сделать в int переменную для хранения количества строк и использовать его в петлю for, как показано ниже:

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

Это небольшое изменение позволит ускорить выполнение значительно в зависимости от количество строк в электронной таблице. Используя тестовый лист с 730 + строками, он занял 2447 миллисекунд с UsedRange в цикле for и 1118 миллисекунд, когда usedRange находился за пределами цикла for. Надеюсь это поможет.

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: изменил код выше, чтобы петли из нижней части файла первенствовать к вершине. Это позволяет избежать изменения списка rowsToDelete.

+0

Я тоже пробовал это, но я не могу заставить его работать. Я уверен, что я делаю что-то неправильно здесь, но я собираюсь поиграть с ним, пока не смогу заставить его работать. Файл excel, который обычно работает, имеет примерно 20.000-30.000 строк. Способ, которым мне удалось сделать эту работу до сих пор (но я попытался сделать ее немного более фантастическим), был в файле filterin в моей первой колонке, а затем знал, что иногда у моего второго и третьего столбца могут быть пробелы, я фильтрую эти чтобы получить пустые строки и удалить их. Но я хотел пойти немного «больше и лучше» об этом. Я опубликую обновление a.s.a.p. Спасибо ! –