Как удалить пустые ячейки в столбцах сразу в 100 столбцах?
1. Нужно все данные (не пустые ячейки) вывести к верху листа, чтобы понимать длину не пустых ячеек каждого столбца. 2. Нужно подровнять столбцы по длине (слева-направо) Есть и пустые столбцы.
Спасибо) См. пример в экселе, тут форматирование не то.
Как удалить пустые ячейки в столбцах сразу в 100 столбцах?
1. Нужно все данные (не пустые ячейки) вывести к верху листа, чтобы понимать длину не пустых ячеек каждого столбца. 2. Нужно подровнять столбцы по длине (слева-направо) Есть и пустые столбцы.
Типа вот так? (Код надо поместить в общий модуль, и вызывать, предварительно выделив область для обработки)
[vba]
Код
Sub testRows00() ' переносим ячейки, анализируя содержимое ' работаем с выделенной областью If Selection.Count = 1 Then Exit Sub For Each col In Selection.Columns Set cellTo = Nothing For Each cell In col.Cells If Not IsEmpty(cell) Then If Not cellTo Is Nothing Then cell.Copy cellTo cell.ClearContents Set cellTo = cellTo.Offset(1) End If Else If cellTo Is Nothing Then Set cellTo = cell End If End If Next Next End Sub
Sub testColumns00()
' работаем с выделенной областью ' сначала выполняем "сжатие" по строкам If Selection.Count = 1 Then Exit Sub testRows00
' выделенная область та же ' ПРЕДУПРЕЖДЕНИЕ: одна строка выше выделенного диапазона будут очищена For Each col In Selection.Columns col.Offset(-1).Cells(1, 1).Value = WorksheetFunction.CountA(col) Next Set rngS = Selection.Offset(-1).Resize(Selection.Rows.Count + 1) With rngS.Parent.Sort .SortFields.Add Key:=rngS.Rows(1), _ SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal .SetRange rngS .Header = xlGuess .Orientation = xlLeftToRight .SortMethod = xlPinYin .Apply End With rngS.Rows(1).ClearContents
End Sub
[/vba] Смеяться не надо Мне было просто нечего делать Например, предложенный Nic70y код [vba]
Код
Sub testRows() ' используя встроенные средства, удаляем пустые ячейки, со сдвигом данных вверх ' ПРЕДУПРЕЖДЕНИЕ: сдвигаются выше данные, расположенные на листе ниже выделенной области ' работаем с выделенной областью If Selection.Count = 1 Then Exit Sub Selection.SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp End Sub
[/vba]не подходит по причине, изложенной в комментариях...
Типа вот так? (Код надо поместить в общий модуль, и вызывать, предварительно выделив область для обработки)
[vba]
Код
Sub testRows00() ' переносим ячейки, анализируя содержимое ' работаем с выделенной областью If Selection.Count = 1 Then Exit Sub For Each col In Selection.Columns Set cellTo = Nothing For Each cell In col.Cells If Not IsEmpty(cell) Then If Not cellTo Is Nothing Then cell.Copy cellTo cell.ClearContents Set cellTo = cellTo.Offset(1) End If Else If cellTo Is Nothing Then Set cellTo = cell End If End If Next Next End Sub
Sub testColumns00()
' работаем с выделенной областью ' сначала выполняем "сжатие" по строкам If Selection.Count = 1 Then Exit Sub testRows00
' выделенная область та же ' ПРЕДУПРЕЖДЕНИЕ: одна строка выше выделенного диапазона будут очищена For Each col In Selection.Columns col.Offset(-1).Cells(1, 1).Value = WorksheetFunction.CountA(col) Next Set rngS = Selection.Offset(-1).Resize(Selection.Rows.Count + 1) With rngS.Parent.Sort .SortFields.Add Key:=rngS.Rows(1), _ SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal .SetRange rngS .Header = xlGuess .Orientation = xlLeftToRight .SortMethod = xlPinYin .Apply End With rngS.Rows(1).ClearContents
End Sub
[/vba] Смеяться не надо Мне было просто нечего делать Например, предложенный Nic70y код [vba]
Код
Sub testRows() ' используя встроенные средства, удаляем пустые ячейки, со сдвигом данных вверх ' ПРЕДУПРЕЖДЕНИЕ: сдвигаются выше данные, расположенные на листе ниже выделенной области ' работаем с выделенной областью If Selection.Count = 1 Then Exit Sub Selection.SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp End Sub
[/vba]не подходит по причине, изложенной в комментариях...AndreTM
Skype: andre.tm.007 Donate: Qiwi: 9517375010
Сообщение отредактировал AndreTM - Суббота, 15.08.2015, 08:46
Не уверен, но в качестве предположения - возможно, код будет работать быстрее, если удалять пустые не сверху вниз, как по умолчанию Excel делает, а насильно прописать удаление по циклу снизу вверх.
Не уверен, но в качестве предположения - возможно, код будет работать быстрее, если удалять пустые не сверху вниз, как по умолчанию Excel делает, а насильно прописать удаление по циклу снизу вверх._Boroda_
у меня 3000 строк и под 200 столбцов. Медленно удаляет. Эксель виснет
Странно... 600 тыс. ячеек для Excel это не тот объем, чтобы виснуть. (если, конечно, у вас не пентиум III )
Попробуйте так (должно работать оч. быстро на любом кол-ве)
[vba]
Код
Sub PackByRows() ' реализация вашего "Нужно1" Dim r&, c&, i&, n&, v() v = Selection.Value n = UBound(v) ' кол-во строк в выделенном диапазоне For c = 1 To UBound(v, 2) ' находим первую пустую ячейку в столбце For i = 1 To n If Len(v(i, c)) = 0 Then Exit For Next ' проверяем остальные ячейки в столбце For r = i + 1 To n If Len(v(r, c)) Then v(i, c) = v(r, c) v(r, c) = Empty i = i + 1 End If Next r, c Selection = v End Sub
у меня 3000 строк и под 200 столбцов. Медленно удаляет. Эксель виснет
Странно... 600 тыс. ячеек для Excel это не тот объем, чтобы виснуть. (если, конечно, у вас не пентиум III )
Попробуйте так (должно работать оч. быстро на любом кол-ве)
[vba]
Код
Sub PackByRows() ' реализация вашего "Нужно1" Dim r&, c&, i&, n&, v() v = Selection.Value n = UBound(v) ' кол-во строк в выделенном диапазоне For c = 1 To UBound(v, 2) ' находим первую пустую ячейку в столбце For i = 1 To n If Len(v(i, c)) = 0 Then Exit For Next ' проверяем остальные ячейки в столбце For r = i + 1 To n If Len(v(r, c)) Then v(i, c) = v(r, c) v(r, c) = Empty i = i + 1 End If Next r, c Selection = v End Sub
regnus, а "Нужно 2" в моём варианте (конечно, заменив в его вызове процедуру testRows00 на PackByRows от KSV всё равно остается медленной? Тогда единственный вариант - считать все данные в массив и провести преобразования уже с ним...
regnus, а "Нужно 2" в моём варианте (конечно, заменив в его вызове процедуру testRows00 на PackByRows от KSV всё равно остается медленной? Тогда единственный вариант - считать все данные в массив и провести преобразования уже с ним...AndreTM
regnus, я не стал делать "Нужно2", т.к. судя по коду (не проверял), процедура testColumns00() от AndreTM должна сортировать быстро. Единственное, ее можно чуть дописать, если у вас выделенный диапазон начинается с первой строки на листе, или чтобы не затереть строку перед выделенным диапазоном.
[vba]
Код
Sub testColumns00() Dim c As Range
' работаем с выделенной областью ' сначала выполняем "сжатие" по строкам If Selection.Count = 1 Then Exit Sub PackByRows
With Selection .Rows(1).Insert For Each c In .Columns c.Cells(0) = WorksheetFunction.CountA(c) Next Set c = .Offset(-1).Resize(.Rows.Count + 1) With .Parent.Sort With .SortFields .Clear .Add c.Rows(1), xlSortOnValues, xlDescending End With .SetRange c .Header = xlNo .Orientation = xlLeftToRight .Apply End With .Rows(0).Delete End With End Sub
[/vba]
regnus, я не стал делать "Нужно2", т.к. судя по коду (не проверял), процедура testColumns00() от AndreTM должна сортировать быстро. Единственное, ее можно чуть дописать, если у вас выделенный диапазон начинается с первой строки на листе, или чтобы не затереть строку перед выделенным диапазоном.
[vba]
Код
Sub testColumns00() Dim c As Range
' работаем с выделенной областью ' сначала выполняем "сжатие" по строкам If Selection.Count = 1 Then Exit Sub PackByRows
With Selection .Rows(1).Insert For Each c In .Columns c.Cells(0) = WorksheetFunction.CountA(c) Next Set c = .Offset(-1).Resize(.Rows.Count + 1) With .Parent.Sort With .SortFields .Clear .Add c.Rows(1), xlSortOnValues, xlDescending End With .SetRange c .Header = xlNo .Orientation = xlLeftToRight .Apply End With .Rows(0).Delete End With End Sub
Вот попробовал сварганить с сортировкой столбцов, вышло многа букфф
[vba]
Код
Public Sub test() Dim i As Integer, j As Integer, k As Integer Dim dC As Integer, dR As Integer Const maxRow As Integer = 25, maxCln As Integer = 25 'задаем размеры для считывания Const lName As String = "buff", lNmBasa As String = "test" 'имена целевого и базового листа Dim arrK(1 To maxCln, 1 To 2) As Integer Dim arr2(1 To maxRow, 1 To maxCln) Dim arrOut(1 To maxRow, 1 To maxCln)
dC = 0 ' delta Colunm если выводить не в А1 dR = 0 ' delta Row If SheetCheck(lName) = 0 Then Sheets.Add.Name = lName Application.StatusBar = "Идёт считывание и сортировка данных..."
Application.ScreenUpdating = False With Sheets(lNmBasa) For j = 1 To maxCln k = 0 For i = 1 To maxRow If .Cells(i, j) <> "" Then k = k + 1 arr2(k, j) = .Cells(i, j) End If Next i DoEvents arrK(j, 1) = j arrK(j, 2) = k Next j Call sortArr(arrK) For i = 1 To maxCln For j = 1 To maxRow arrOut(j, maxCln + 1 - i) = arr2(j, arrK(i, 1)) Next j Next i End With Sheets(lName).Cells(1 + dR, 1 + dC).Resize(maxRow, maxCln).ClearContents Sheets(lName).Cells(1 + dR, 1 + dC).Resize(maxRow, maxCln) = arrOut
Application.ScreenUpdating = True Application.StatusBar = "Вывод данных закончен" End Sub
Function SheetCheck(ByVal ShName As String) As Byte Dim x As Byte
x = 0 For Each ws In ActiveWorkbook.Sheets If ws.Name = ShName Then x = 1 Exit For End If Next ws SheetCheck = x End Function
Private Sub sortArr(arr1() As Integer) Dim fOut As Byte Dim LBdr As Integer, RBdr As Integer Dim buff1 As Integer Dim str1 As String
LBdr = 1 RBdr = UBound(arr1, 1) Do While 1 fOut = 1 For i = 1 To RBdr - 1 If arr1(i, 2) > arr1(i + 1, 2) Then k = i fOut = 0 buff1 = arr1(i, 1) arr1(i, 1) = arr1(i + 1, 1) arr1(i + 1, 1) = buff1 buff1 = arr1(i, 2) arr1(i, 2) = arr1(i + 1, 2) arr1(i + 1, 2) = buff1 End If Next i If fOut Then Exit Do RBdr = k fOut = 1
For i = RBdr To LBdr + 1 Step -1 If arr1(i, 2) < arr1(i - 1, 2) Then k = i fOut = 0 buff1 = arr1(i, 1) arr1(i, 1) = arr1(i - 1, 1) arr1(i - 1, 1) = buff1 buff1 = arr1(i, 2) arr1(i, 2) = arr1(i - 1, 2) arr1(i - 1, 2) = buff1 End If Next i If fOut Then Exit Do LBdr = k Loop
End Sub
[/vba]
Вот попробовал сварганить с сортировкой столбцов, вышло многа букфф
[vba]
Код
Public Sub test() Dim i As Integer, j As Integer, k As Integer Dim dC As Integer, dR As Integer Const maxRow As Integer = 25, maxCln As Integer = 25 'задаем размеры для считывания Const lName As String = "buff", lNmBasa As String = "test" 'имена целевого и базового листа Dim arrK(1 To maxCln, 1 To 2) As Integer Dim arr2(1 To maxRow, 1 To maxCln) Dim arrOut(1 To maxRow, 1 To maxCln)
dC = 0 ' delta Colunm если выводить не в А1 dR = 0 ' delta Row If SheetCheck(lName) = 0 Then Sheets.Add.Name = lName Application.StatusBar = "Идёт считывание и сортировка данных..."
Application.ScreenUpdating = False With Sheets(lNmBasa) For j = 1 To maxCln k = 0 For i = 1 To maxRow If .Cells(i, j) <> "" Then k = k + 1 arr2(k, j) = .Cells(i, j) End If Next i DoEvents arrK(j, 1) = j arrK(j, 2) = k Next j Call sortArr(arrK) For i = 1 To maxCln For j = 1 To maxRow arrOut(j, maxCln + 1 - i) = arr2(j, arrK(i, 1)) Next j Next i End With Sheets(lName).Cells(1 + dR, 1 + dC).Resize(maxRow, maxCln).ClearContents Sheets(lName).Cells(1 + dR, 1 + dC).Resize(maxRow, maxCln) = arrOut
Application.ScreenUpdating = True Application.StatusBar = "Вывод данных закончен" End Sub
Function SheetCheck(ByVal ShName As String) As Byte Dim x As Byte
x = 0 For Each ws In ActiveWorkbook.Sheets If ws.Name = ShName Then x = 1 Exit For End If Next ws SheetCheck = x End Function
Private Sub sortArr(arr1() As Integer) Dim fOut As Byte Dim LBdr As Integer, RBdr As Integer Dim buff1 As Integer Dim str1 As String
LBdr = 1 RBdr = UBound(arr1, 1) Do While 1 fOut = 1 For i = 1 To RBdr - 1 If arr1(i, 2) > arr1(i + 1, 2) Then k = i fOut = 0 buff1 = arr1(i, 1) arr1(i, 1) = arr1(i + 1, 1) arr1(i + 1, 1) = buff1 buff1 = arr1(i, 2) arr1(i, 2) = arr1(i + 1, 2) arr1(i + 1, 2) = buff1 End If Next i If fOut Then Exit Do RBdr = k fOut = 1
For i = RBdr To LBdr + 1 Step -1 If arr1(i, 2) < arr1(i - 1, 2) Then k = i fOut = 0 buff1 = arr1(i, 1) arr1(i, 1) = arr1(i - 1, 1) arr1(i - 1, 1) = buff1 buff1 = arr1(i, 2) arr1(i, 2) = arr1(i - 1, 2) arr1(i - 1, 2) = buff1 End If Next i If fOut Then Exit Do LBdr = k Loop
А если в код ещё добавить отключение/включение Application.ScreenUpdating - то тоже быстродействие поднимется. Вотбы вам сразу спросить - "как БЫСТРО проделать данную операцию на таком-то объёме"...
А если в код ещё добавить отключение/включение Application.ScreenUpdating - то тоже быстродействие поднимется. Вотбы вам сразу спросить - "как БЫСТРО проделать данную операцию на таком-то объёме"...AndreTM
Skype: andre.tm.007 Donate: Qiwi: 9517375010
Сообщение отредактировал AndreTM - Воскресенье, 16.08.2015, 12:44
Собрал конструкцию из разных файлов, быстро ли работает не знаю. Диапазон сортировки нужно указывать в макросе, может кто переделает под выделение. Сортируются столбцы начиная с нижней строки. Результат не отличается от результата Udik.
Собрал конструкцию из разных файлов, быстро ли работает не знаю. Диапазон сортировки нужно указывать в макросе, может кто переделает под выделение. Сортируются столбцы начиная с нижней строки. Результат не отличается от результата Udik.gling
Собрал конструкцию из разных файлов, быстро ли работает не знаю. Диапазон сортировки нужно указывать в макросе, может кто переделает под выделение. Сортируются столбцы начиная с нижней строки. Результат не отличается от результата Udik
Ваш пример работает. А мой нет. Вставляет 2 столбца в один. Не сортирует столбцы. удалено администрацией
Собрал конструкцию из разных файлов, быстро ли работает не знаю. Диапазон сортировки нужно указывать в макросе, может кто переделает под выделение. Сортируются столбцы начиная с нижней строки. Результат не отличается от результата Udik
Ваш пример работает. А мой нет. Вставляет 2 столбца в один. Не сортирует столбцы. удалено администрациейregnus
Сообщение отредактировал _Boroda_ - Понедельник, 17.08.2015, 16:38
regnus, что у вас не работает? Вариант, предложенный вам AndreTM, прекрасно работает. Вы это пробовали? Должно работать достаточно быстро (приемлимо быстро). Можно еще на время сортировки временно отключать обновление экрана и авторасчет формул (если их у вас много)
' работаем с выделенной областью ' сначала выполняем "сжатие" по строкам If Selection.Count = 1 Then Exit Sub PackByRows
With Selection .Rows(1).Insert For Each c In .Columns c.Cells(0) = WorksheetFunction.CountA(c) Next Set c = .Offset(-1).Resize(.Rows.Count + 1) With .Parent.Sort With .SortFields .Clear .Add c.Rows(1), xlSortOnValues, xlDescending End With .SetRange c .Header = xlNo .Orientation = xlLeftToRight .Apply End With .Rows(0).Delete End With
' вкл. все, что отключали ActiveSheet.EnableCalculation = True Application.ScreenUpdating = True End Sub
[/vba]
regnus, что у вас не работает? Вариант, предложенный вам AndreTM, прекрасно работает. Вы это пробовали? Должно работать достаточно быстро (приемлимо быстро). Можно еще на время сортировки временно отключать обновление экрана и авторасчет формул (если их у вас много)
' работаем с выделенной областью ' сначала выполняем "сжатие" по строкам If Selection.Count = 1 Then Exit Sub PackByRows
With Selection .Rows(1).Insert For Each c In .Columns c.Cells(0) = WorksheetFunction.CountA(c) Next Set c = .Offset(-1).Resize(.Rows.Count + 1) With .Parent.Sort With .SortFields .Clear .Add c.Rows(1), xlSortOnValues, xlDescending End With .SetRange c .Header = xlNo .Orientation = xlLeftToRight .Apply End With .Rows(0).Delete End With
' вкл. все, что отключали ActiveSheet.EnableCalculation = True Application.ScreenUpdating = True End Sub
regnus, я не стал делать "Нужно2", т.к. судя по коду (не проверял), процедура testColumns00() от AndreTM должна сортировать быстро. Единственное, ее можно чуть дописать, если у вас выделенный диапазон начинается с первой строки на листе, или чтобы не затереть строку перед выделенным диапазоном.
Пробую ваш файл, т.к. вроде он делает 2 варианта.
500 строк и 100 столбцов обрабатывает за 1-3 минуты. Точно не скажу, т.к. при обработке виснет.
А 3000 строк и 100 столбцов появляется жесть. Эксель зависает минут на 20 и более Начинает глючить и не открывает другие файлы. Приходится перегружать комп...как будто эксель вирус хватает.
Есть способы не вешать эксель и ускорить обработку?
regnus, я не стал делать "Нужно2", т.к. судя по коду (не проверял), процедура testColumns00() от AndreTM должна сортировать быстро. Единственное, ее можно чуть дописать, если у вас выделенный диапазон начинается с первой строки на листе, или чтобы не затереть строку перед выделенным диапазоном.
Пробую ваш файл, т.к. вроде он делает 2 варианта.
500 строк и 100 столбцов обрабатывает за 1-3 минуты. Точно не скажу, т.к. при обработке виснет.
А 3000 строк и 100 столбцов появляется жесть. Эксель зависает минут на 20 и более Начинает глючить и не открывает другие файлы. Приходится перегружать комп...как будто эксель вирус хватает.
Есть способы не вешать эксель и ускорить обработку?regnus
Сообщение отредактировал regnus - Понедельник, 17.08.2015, 20:49