/ / Con declaración para evitar ejecutar código en una hoja en blanco - vba, excel-vba, excel

Con una declaración para evitar ejecutar código en una hoja en blanco: vba, excel-vba, excel

A continuación se muestra un sub para copiar el rango de datos dinámicos de Sheet1 a Sheet2 (esta última es una hoja de trabajo protegida por contraseña).

Funciona bien excepto lRowSh2 y lColSh2 causar un error crítico si Sheet2 está completamente en blanco.

Hay algun tipo de If declaración que puedo usar para que la parte para borrar la Hoja2 se omita si las celdas están en blanco (nota: es posible que hayan tenido un valor en el pasado)?

Solo para mayor claridad, la Fila 6 es la fila de encabezado en ambas hojas.

Sub CopyData()
Application.ScreenUpdating = False

Dim lRowSh1 As Long, lColSh1 As Long, lRowSh2 As Long, lColSh2 As Long
Dim Sheet1Data() As Variant

" Warning message before proceeding with data transfer to sample selection worksheet.
If MsgBox("Copy data to Sheet2? (this will overwrite existing data in Sheet2)", _
vbYesNo + vbCritical) = vbYes _
Then

With Sheets("Sheet1")

" Determines last row and column of Sheet1 data range.
lRowSh1 = .Cells.Find("*", .Cells(1, 1), , , xlByRows, xlPrevious).Row
lColSh1 = .Cells.Find("*", .Cells(1, 1), , , xlByColumns, xlPrevious).Column
" Loads Sheet1 data range (row 6 to last row for all columns) into array Sheet1Data.
Sheet1Data = .Range(.Cells(6, 1), .Cells(lRowSh1, lColSh1)).Value

End With

With Sheets("Sheet2")
" Lifts worksheet protection for execution of code
.Unprotect Password:="admin"

" Removes any existing filters in Sheet2.
If .AutoFilterMode = True Then .AutoFilter.ShowAllData

" Determines last row and column of any pre-existing data in Sheet2 and clears:
lRowSh2 = .Cells.Find("*", .Cells(1, 1), , , xlByRows, xlPrevious).Row
lColSh2 = .Cells.Find("*", .Cells(1, 1), , , xlByColumns, xlPrevious).Column
.Range(.Cells(6, 1), .Cells(lRowSh2, lColSh2)).ClearContents

" Repopulates with the contents of array Sheet1Data:
.Range(.Cells(6, 2), .Cells(lRowSh1, lColSh1 + 1)).Value = Sheet1Data

" Autofit repopulated columns:
.Cells.EntireColumn.AutoFit

" Reapply AutoFilter to header (Row 6):
.Cells(6, 1) = " "
.Cells(6, 1).EntireRow.AutoFilter

" Reapply worksheet protection after execution of code:
.Protect Password:="admin", userinterfaceonly:=True, AllowFiltering:=True
.EnableSelection = xlNoRestrictions

End With

End If

Application.ScreenUpdating = True

End Sub

Respuestas

2 para la respuesta № 1

Tu problema es que Find(What:="*").Row no existe si la búsqueda no tuvo éxito.

Find siempre devuelve un rango, ya sea que la búsqueda se haya realizado correctamente o no.

Si la búsqueda no ha tenido éxito, el valor de ese rango será Nothing. Nada no tiene propiedades, por lo que cualquier intento de acceder a las propiedades del rango fallará.

Necesitas algo como esto:

Option Explicit
Sub Test()

Dim RngCrnt As Range

With Worksheets("Sheet2")

Set RngCrnt = .Cells.Find(What:="*")

If RngCrnt Is Nothing Then
" Code to handle empty worksheet
Debug.Print "Worksheet empty"
Else
" Code to handle non-empty worksheet
Debug.Print "Cell(" & RngCrnt.Row & ", " & RngCrnt.Column & ") contains a value"
End If

End With

End Sub

0 para la respuesta № 2

si .usedrange.cells.count> 1 y .range ("a1") = "" entonces

será cierto si la hoja está en blanco


0 para la respuesta № 3

Como la fila del encabezado siempre tendrá un valor si la hoja contiene datos, decidí simplemente marcar una celda en esa línea:

If .Cells(6.2) Is Nothing Then
Else
lRowSh2 = .Cells.Find("*", .Cells(1, 1), , , xlByRows, xlPrevious).Row
lColSh2 = .Cells.Find("*", .Cells(1, 1), , , xlByColumns, xlPrevious).Column
.Range(.Cells(6, 1), .Cells(lRowSh2, lColSh2)).ClearContents

End If

0 para la respuesta № 4

¿Qué tal una versión simple?

if isempty(usedrange)

en este caso incluso si se usa rango en las hojas pero está completamente en blanco lo tomará como vacío