Excel 高效地删除工作表中所有隐藏的列和行

Excel 高效地删除工作表中所有隐藏的列和行,excel,vba,hidden,Excel,Vba,Hidden,要删除我正在使用的工作表中所有隐藏的列和行,请执行以下操作: With activeworkbook.Sheets(1) LR = LRow(activeworkbook.Sheets(1)) ' will retrieve last row no in the sheet lc = LCol(activeworkbook.Sheets(1)) ' will retrieve last column no in the sheet

要删除我正在使用的工作表中所有隐藏的列和行,请执行以下操作:

 With activeworkbook.Sheets(1)

           LR = LRow(activeworkbook.Sheets(1)) ' will retrieve last row no in the sheet
           lc = LCol(activeworkbook.Sheets(1)) ' will retrieve last column no in the sheet

            For lp = lc To 1 Step -1    'loop through all columns
                If .Columns(lp).EntireColumn.Hidden = True Then .Columns(lp).EntireColumn.Delete
            Next lp

            For lp = LR To 1 Step -1    'loop through all rows
                If .Rows(lp).EntireRow.Hidden = True Then .Rows(lp).EntireRow.Delete
            Next
end with
但这需要很长时间,因为我有300多列和1000行。当我试图估算上述操作所需的总时间时,我发现以下几行花费的时间最多:

For lp = lc To 1 Step -1    'loop through all columns
    If .Columns(lp).EntireColumn.Hidden = True Then _
         .Columns(lp).EntireColumn.Delete
Next lp
但是下一个循环要快得多

你对提高执行速度有什么建议吗

LRow和LCol函数的代码如下,我确认它返回正确的最后一行和最后一列:

Function LRow(sh As Worksheet)
    On Error Resume Next
    LRow = sh.Cells.Find(What:="*", _
                            After:=sh.Range("A1"), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlPrevious, _
                            matchCase:=False).Row
    On Error GoTo 0
End Function


Function LCol(sh As Worksheet)
    On Error Resume Next
    LCol = sh.Cells.Find(What:="*", _
                            After:=sh.Range("A1"), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByColumns, _
                            SearchDirection:=xlPrevious, _
                            matchCase:=False).Column
    On Error GoTo 0
End Function

我正在考虑使用.specialcells来选择所有可见列,并将其反向删除

您可以先扫描行和列,然后批量删除它们,请看以下内容:

Sub cooolboy()

Dim Ws As Worksheet, _
    lp As Long, _
    lR As Long, _
    lC As Integer, _
    RowToDelete As String, _
    ColToDelete As String

Set Ws = ActiveWorkbook.Sheets("Sheet4")
RowToDelete = ""
ColToDelete = ""

With Ws
    lR = .Range("A" & .Rows.Count).End(xlUp).Row         'will retrieve last row no in the sheet
    lC = .Cells(1, .Columns.Count).End(xlToLeft).Column  'will retrieve last column no in the sheet

    For lp = 1 To lC    'loop through all columns
        If .Columns(lp).EntireColumn.Hidden Then _
            ColToDelete = ColToDelete & "," & Col_Letter(lp) & ":" & Col_Letter(lp)
    Next lp

    For lp = 1 To lR   'loop through all rows
        If .Rows(lp).EntireRow.Hidden Then _
            RowToDelete = RowToDelete & "," & lp & ":" & lp
    Next lp
    'Get rid of the first comma
    If ColToDelete <> "" Then ColToDelete = Right(ColToDelete, Len(ColToDelete) - 1)
    If RowToDelete <> "" Then RowToDelete = Right(RowToDelete, Len(RowToDelete) - 1)
    'MsgBox ColToDelete & vbCrLf & RowToDelete
    If ColToDelete <> "" Then .Range(ColToDelete).Delete Shift:=xlToLeft
    If RowToDelete <> "" Then .Range(RowToDelete).Delete Shift:=xlUp
End With

End Sub

Function Col_Letter(lngCol As Long) As String
Dim vArr
vArr = Split(Cells(1, lngCol).Address(True, False), "$")
Col_Letter = vArr(0)
End Function
Sub-cooolboy()
将Ws设置为工作表_
只要_
只要_
lC为整数_
RowToDelete作为字符串_
ColToDelete作为字符串
设置Ws=ActiveWorkbook.Sheets(“Sheet4”)
Rowtodelet=“”
ColToDelete=“”
与Ws
lR=.Range(“A”&.Rows.Count).End(xlUp.Row)”将检索工作表中的最后一行编号
lC=.Cells(1,.Columns.Count).End(xlToLeft).Column'将检索工作表中的最后一列编号
对于lp=1至lC'循环通过所有列
如果.Columns(lp).entireclumn.Hidden则_
ColToDelete=ColToDelete&“,”和Col_字母(lp)&“:”和Col_字母(lp)
下一个lp
对于lp=1到lR'循环通过所有行
如果.Rows(lp).EntireRow.Hidden则_
RowToDelete=RowToDelete&“,”&lp&“:”&lp
下一个lp
'去掉第一个逗号
如果ColToDelete“”则ColToDelete=Right(ColToDelete,Len(ColToDelete)-1)
如果RowToDelete“”则RowToDelete=Right(RowToDelete,Len(RowToDelete)-1)
'MsgBox ColToDelete&vbCrLf&rowtolete
如果是ColToDelete“”,则.Range(ColToDelete).Delete Shift:=xlToLeft
如果是RowToDelete“”,则.Range(RowToDelete).Delete Shift:=xlUp
以
端接头
函数列字母(与字符串一样长)
暗变
vArr=拆分(单元格(1,lngCol).Address(真,假),“$”)
Col_字母=vArr(0)
端函数

此外,请看这篇文章,查找最后一行和最后一列:

我使用特殊单元格成功地实现了它,如下所示。这比以前的方法快得多,并且在Excel 2010以后的版本中运行良好

Set urng = Activeworkbook.Sheets(1).UsedRange.SpecialCells(xlCellTypeVisible)
                If Not urng Is Nothing Then
                    s = Split(urng.Cells(1, 1).Address, "$")
                    LR = LRow(Activeworkbook.Sheets(1))
                    lc = LCol(Activeworkbook.Sheets(1))
                    icol = urng.Cells(1, 1).Column

' delete hidden colums
                    Set urng2 = Activeworkbook.Sheets(1).Range(Cells(s(2), 1), Cells(s(2), lc))
                    Set oVisible = urng2.SpecialCells(xlCellTypeVisible)
                    Set oHidden = urng2

                    oHidden.EntireColumn.Hidden = False
                    oVisible.EntireColumn.Hidden = True

                    Set oHidden = urng2.SpecialCells(xlCellTypeVisible)
                    oHidden.EntireColumn.Delete
                    oVisible.EntireColumn.Hidden = False

' delete hidden rows
                    Set urng = Activeworkbook.Sheets(1).UsedRange.SpecialCells(xlCellTypeVisible)
                    If Not urng Is Nothing Then
                        's = Split(urng.Cells(1, 1).Address, "$")
                        icol = urng.Cells(1, 1).Column

                        Set urng2 = Activeworkbook.Sheets(1).Range(Cells(1, icol), Cells(LR, icol))
                        'urng2.Select
                        Set oVisible = urng2.SpecialCells(xlCellTypeVisible)
                        Set oHidden = urng2

                        oHidden.EntireRow.Hidden = False
                        oVisible.EntireRow.Hidden = True

                        Set oHidden = urng2.SpecialCells(xlCellTypeVisible)
                        oHidden.EntireRow.Delete
                        oVisible.EntireRow.Hidden = False

                    End If
                End If

如果您确认
LCol(…)
函数返回的列正确,那就太好了。由于这通常是一个简短的代码行,我怀疑这样的子函数是否必要,更不用说返回正确的列索引号了。使用
Applciation.screenUpdate=False
加快速度。如果要删除公式,请将计算设置为
xlCalculationManual
EnableEvents
通常也会中断几毫秒。如果切换两个循环,即先删除行,然后删除列,会发生什么情况?问得好,已尝试并确认仍然删除行比删除列快得多。使用OP中提到的所有设置尝试:谢谢…执行上述代码时,我在.Range(ColToDelete).Delete Shift:=xlToLeftSilly处遇到应用程序定义或对象定义错误,但您是否确保有隐藏列?因为它对我来说很好。。。我只是没有测试它只有一行或一列。看一看编辑中的更正。我尝试了几个列,但对很多列都不起作用……例如,我尝试删除ColtoDeleteW:EW,EV:EV,EU:EU,ET:ET,ES:ES,ER:ER,EQ:EQ,EP:EP,EO:EO,EN:EN,EM:EM,EL,EK:EK,EJ:EJ,EI:EI,EH:EH,BY:BY,BX,BW:BW,BV,BU:BU,BT:BT,BS,BS:BR,BQ:BQ,北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京:北京,北京:北京:北京:北京:北京:北京,北京:北京:北京,北京:北京:北京:北京:北京,北京:北京:北京,BB:北京,BB:北京:北京:北京,BB:北京,BB:北京,BB:北京,BB:北京,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB,BB:BB,BB:BB R,Q:Q,P:P,O:O,N:N,M:M,L:L,K:K,J:J,I:I,H:H,G:G,F:F,E:E,D:D,C:C,B:BOkay。。。因此,如果您定义了一个计数器,并在什么限制之后进行检查,这可能不再起作用,然后退出循环以删除这些计数器并重新启动循环(您需要定义另一个变量以重新启动先前扫描的最后一列/行上的循环)。让我知道结果如何!