Script para eliminar las filas vacías en una hoja -- vba campo con excel camp codereview Relacionados El problema

Script for removing empty rows in a sheet


4
vote

problema

Español

A menudo recibo hojas de trabajo de Excel (con filas vacías) que tengo que procesar como una mesa pivote. Debido a que las mesas de pivote no permiten filas vacías, he hecho este script. Cualquier retroalimentación es bienvenida.

  ' Removes empty rows from an sheet.  Public Sub RemoveEmptyLines()   Dim lastRow As Long   Dim currentRow As Long   Dim emptyLine As Boolean   Dim answer As Integer   Dim countDeleted As Integer    Application.ScreenUpdating = False    answer = MsgBox("Empty lines will be deleted." & vbLf & _              "Do you wish to continue?", _               vbYesNo, "Changing table-structure?")    If answer = vbYes Then     ' Minus 1 => The last one we check will be the last     ' but one row.     lastRow = Range("A1").SpecialCells(xlCellTypeLastCell).row - 1     currentRow = 1     countDeleted = 0     ' Go until the last but two row! The last row can't     ' be empty (Result of SpecialCells). So we don't have     ' to check that.     While currentRow < lastRow        emptyLine = True        Do         ' When the complete row is empty then delete it.         ' Table structure might be changed while iterating         ' through the inner loop. So repeat the check from         ' the main loop.         If _            WorksheetFunction.CountA(Rows(currentRow + 1).EntireRow) = 0 _         And _            currentRow < lastRow _         Then            Rows(currentRow + 1).EntireRow.Delete           countDeleted = countDeleted + 1           lastRow = lastRow - 1          Else           ' I case of "not empty" leave the inner loop and           ' check the next line.           emptyLine = False          End If        Loop Until emptyLine = False        currentRow = currentRow + 1     Wend      MsgBox countDeleted & " rows have been deleted.", _            vbInformation, "Result"    End If    Application.ScreenUpdating = True  End Sub   
Original en ingles

I often receive Excel worksheets (with empty rows) which I have to process as a pivot table. Because pivot tables don't allow empty rows, I've made this script. Any feedback is welcomed.

' Removes empty rows from an sheet.  Public Sub RemoveEmptyLines()   Dim lastRow As Long   Dim currentRow As Long   Dim emptyLine As Boolean   Dim answer As Integer   Dim countDeleted As Integer    Application.ScreenUpdating = False    answer = MsgBox("Empty lines will be deleted." & vbLf & _              "Do you wish to continue?", _               vbYesNo, "Changing table-structure?")    If answer = vbYes Then     ' Minus 1 => The last one we check will be the last     ' but one row.     lastRow = Range("A1").SpecialCells(xlCellTypeLastCell).row - 1     currentRow = 1     countDeleted = 0     ' Go until the last but two row! The last row can't     ' be empty (Result of SpecialCells). So we don't have     ' to check that.     While currentRow < lastRow        emptyLine = True        Do         ' When the complete row is empty then delete it.         ' Table structure might be changed while iterating         ' through the inner loop. So repeat the check from         ' the main loop.         If _            WorksheetFunction.CountA(Rows(currentRow + 1).EntireRow) = 0 _         And _            currentRow < lastRow _         Then            Rows(currentRow + 1).EntireRow.Delete           countDeleted = countDeleted + 1           lastRow = lastRow - 1          Else           ' I case of "not empty" leave the inner loop and           ' check the next line.           emptyLine = False          End If        Loop Until emptyLine = False        currentRow = currentRow + 1     Wend      MsgBox countDeleted & " rows have been deleted.", _            vbInformation, "Result"    End If    Application.ScreenUpdating = True  End Sub 
     
         
         

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Tu macro hace lo que pretende, pero de una manera muy confusa.

While en funcionamiento, en realidad no está analizando el currentRow PERO EL currentRow + 1 . Para algo así, preferiría un nombre como baseRow porque implica que se realizarán otros cálculos en la parte superior. En cualquier caso, sería mucho más sencillo simplemente seguir adelante a primera fila y evitar todo el desorden de la numeración de la línea.


IMO, si tiene una macro llamada RemoveEmptyLines (presumiblemente conectada a un botón descriptivo de nombre), solicitando al usuario que confirme que es lo que quieren hacer es innecesario y probablemente molesto para el usuario -Experiencia.


No soy un fanático de usar las funciones de la hoja de trabajo en VBA, especialmente cuando se usa para determinar el estado actual de la hoja de trabajo. Excel es notoriamente poco fiable en mantener una versión actualizada actualizada de cosas como $query0 , 99887766555443311 etc.

Si desea conocer la fila final a través de todas las columnas 10,000 extrañas, entonces está un poco atascado con él, pero creo que eso es una exageración. Si alguien le envía una hoja de cálculo de datos, debe haber al menos una columna en algún lugar que contenga datos para cada fila. Pueden ser nombres, pueden ser números de identificación / referencia, pueden ser fechas, etc.

Estructuraría su Sub como un procedimiento que realice una referencia de columna como argumento, o solicita al usuario que ingrese, luego usa esa columna por la base de la determinación de su final.


También debe evitar múltiples acciones de eliminación. Está bien para las hojas de trabajo pequeñas, pero intente eliminar una fila en una hoja de trabajo con lotes de datos y puede tomar un tiempo long, cada uno . En su lugar, crearía un rango, nombre IT $query2 y use $query3 para agregar cualquier nueva "filas a eliminar" a ella. Luego, puede tener una sola acción de eliminar al final de su Sub y hágalo todo de una vez.


Tu Sub Luego se ve así:

  $query4  

Succinto, claro, fácil de leer y entender.

 

Your macro does what you intend, but in a very confusing manner.

Whilst running, you're not actually analysing the currentRow but the currentRow + 1. For something like that I'd prefer a name like baseRow because it implies that other calculations will be done on top of it. In any case, it would be much simpler to just go last-row to first and avoid all the line-numbering messiness.


IMO, if you have a macro called RemoveEmptyLines (presumably attached to some descriptively-named Button) then asking the user to confirm that is what they want to do is unnecessary and probably annoying to the User-Experience.


I'm also not a fan of using worksheet functions in VBA, especially when used to determine the current state of the worksheet. Excel is notoriously unreliable at maintaining an accurate up-to-date version of things like usedRange, lastCell etc.

If you want to know the final row across all 10,000-odd columns then you're kinda stuck with it, but I think that's overkill. If somebody sends you a spreadsheet of data, there should be at least one column somewhere which contains data for every row. Might be names, might be ID/Reference numbers, might be dates etc.

I would structure your sub as a procedure that takes a column reference as an argument, or asks the user to input it, then uses that column for the basis of determining your finalRow.


You should also avoid multiple delete actions. It's fine for small worksheets, but try deleting a row in a worksheet with lots of data and it can take a long time, each time. Instead, I would create a range, name it deleteRange and use Union() to add any new "rows to be deleted" to it. Then, you can have just one delete action at the end of your sub and do it all in one go.


Your sub then looks like this:

Option Explicit  Public Sub RemoveEmptyLines()      Application.ScreenUpdating = False     Application.EnableEvents = False     Application.Calculation = xlCalculationManual      Dim columnReference As String     columnReference = InputBox("Please input the Letter-Reference of the key data column")      Dim columnNumber As Long     On Error Resume Next '/ Check that it is a valid reference         columnNumber = Columns(columnReference).Column     On Error GoTo 0      If Not columnNumber > 0 Then         MsgBox "Your column reference was not recognised, please try again"         Exit Sub     End If       Dim lastRow As Long, firstRow As Long, currentRow As Long     Dim lineIsEmpty As Boolean     Dim deleteRange As Range     Dim deleteCount As Long      last Row = Cells(Rows.Count, columnNumber).End(xlUp).Row      firstRow = 1     For currentRow = lastRow To firstRow Step -1           lineIsEmpty = (Cells(currentRow, Columns.Count).End(xlToLeft).Column = 1 And IsEmpty(Cells(currentRow, 1)) And IsEmpty(Cells(currentRow, Columns.Count)))          If lineIsEmpty Then             If deleteRange Is Nothing Then Set deleteRange = Cells(currentRow, 1) Else Set deleteRange = Union(deleteRange, Cells(currentRow, 1))             deleteCount = deleteCount + 1         End If      Next currentRow      If Not deleteRange Is Nothing Then deleteRange.EntireRow.Delete      MsgBox deleteCount & " rows have been deleted.", vbInformation, "Result"      Application.ScreenUpdating = True     Application.EnableEvents = True     Application.Calculation = xlCalculationAutomatic  End Sub 

Succinct, clear, easy to read and understand.

 
 
4
 
vote

Si la clasificación de los datos no ayuda a mover los espacios en blanco al final del rango de datos, y la eliminación de las filas es una mejor solución, dados sus datos, entonces puede probar este enfoque.

Si sabe que una columna siempre tendrá datos (y nunca estará en blanco) para una fila válida, puede lograr las eliminaciones sin un bucle.

  Sub DeleteRows()   'All rows at or after `FirstRow` with a blank value in Column `ColName` will be deleted   Const ColName As String = "A"   Const FirstRow As Long = 1    With ActiveSheet     .Range(ColName & FirstRow & ":" & ColName & .Range(ColName & .Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeBlanks).EntireRow.Delete   End With  End Sub   
 

If sorting the data doesn't help move the blanks to the end of the data range, and deleting the rows is a better solution, given your data, then you can try this approach.

If you know a column will always have data (and never be blank) for a valid row, then you can achieve the deletions without a loop.

Sub DeleteRows()   'All rows at or after `FirstRow` with a blank value in Column `ColName` will be deleted   Const ColName As String = "A"   Const FirstRow As Long = 1    With ActiveSheet     .Range(ColName & FirstRow & ":" & ColName & .Range(ColName & .Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeBlanks).EntireRow.Delete   End With  End Sub 
 
 
   
   

Relacionados problema

6  Fijación de archivos de reclamación médica a través del archivo de texto Lea / escribe  ( Fixing medical claim files through text file read write ) 
Con Gracias a @ Mat'Smug y @comintern por su aliento, aquí hay un programa que escribí para ayudar a mi equipo a reparar archivos de reclamación médica. El ...

5  Copiando datos de libros cerrados  ( Copying data from closed workbooks ) 
Soy un pasante en una empresa industrial en Brasil y sucede que estoy usando mucho en Excel. Acabo de empezar a jugar con VBA hace un par de días, ¡y me divie...

2  Importando datos en Excel  ( Importing data into excel ) 
¿Existe una forma más fácil de importar datos en una matriz de Excel u otra estructura de datos? He intentado investigar colecciones, pero he encontrado la D...

2  Búsqueda de pruebas de abstracción y unidad en mesa Excel  ( Abstracting and unit testing lookups in excel table ) 
Fondo Tengo una solución de VBA que utilizo para ingerir informes de texto de inversión y reformatearlos para su análisis en Excel. Funciona, pero las macro...

5  Excel a JSON Parser con http descargar  ( Excel to json parser with http download ) 
He estado trabajando en un proyecto ( enlace ) a Descargue una hoja de cálculo de Ransomware y propiedades conocidas y conviértase en JSON para que pueda cons...

3  Coloque el cálculo del costo del campamento de verano utilizando las hojas de Google  ( Summer camp cost calculation using google sheets ) 
Estoy haciendo una hoja que suma el costo total para un campamento de verano después del registro. Cada padre puede registrarse hasta cinco niños. Ya he hecho...

3  Comparando células de dos hojas de trabajo  ( Comparing cells of two worksheets ) 
Con el siguiente código, trato de comparar el contenido de dos hojas de trabajo. La primera columna contiene una clave que es única y las siguientes columnas ...

6  Crear tabla que enumera la visibilidad de la hoja de trabajo  ( Create table that lists worksheet visibility ) 
Siguiendo mi pregunta anterior crear Una tabla que enumera las macros en un libro de trabajo o hoja de trabajo Aquí está mi Sub para determinar la visibilid...

7  Recuperando datos de archivos en la carpeta  ( Retrieving data from files in the folder ) 
Estoy a usar el código VBA para simplemente recuperar ciertos datos de todos los archivos de Excel en cierta carpeta y pegarlo en la hoja de cálculo de trabaj...

6  Juego de serpientes - Dentro de la hoja de trabajo - Celdas como píxeles  ( Snake game within worksheet cells as pixels ) 
Desde mi intento bastante mediocre de hacer un juego de invasores del espacio, me topé con un caché de juegos de Visual Basic para solicitar juegos escritos p...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos