【问题标题】:Delete blank cells in a column删除列中的空白单元格
【发布时间】:2016-12-02 01:23:04
【问题描述】:

以下代码将值表转换为单列。

问题是,对于我的表格,每列中的行数对于每个连续的列都会减少一。类似于下表。

我对编写代码非常陌生,只知道非常基础的知识。我复制了一个在线找到的脚本,将一系列值转换为单列。我为删除任何空白单元格而编写的代码部分极大地减慢了代码速度。将大约 250,000 个点转换为一列大约需要 9 个小时。我希望减少处理时间,因为这是我希望经常使用的脚本。

Sub CombineColumns()

Application.ScreenUpdating = False
Application.EnableEvents = False

Dim rng As Range
Dim iCol As Long
Dim lastCell As Long
Dim K As Long

K = 484
'set K equal to the number of data points that created the range


Set rng = ActiveCell.CurrentRegion
lastCell = rng.Columns(1).Rows.count + 1

For iCol = 2 To rng.Columns.count
    Range(Cells(1, iCol), Cells(rng.Columns(iCol).Rows.count, iCol)).Cut
    ActiveSheet.Paste Destination:=Cells(lastCell, 1)
    lastCell = lastCell + rng.Columns(iCol).Rows.count

Next iCol
Dim z As Long
Dim m As Long

z = K ^ 2

For Row = z To 1 Step -1
    If Cells(Row, 1) = 0 Then
    Range("A" & Row).Delete Shift:=xlUp

    Application.StatusBar = "Progress: " & Row & " of z: " & Format((z - Row) / z, "Percent")
    DoEvents

    End If

Next

Application.StatusBar = False
Application.ScreenUpdating = True
Application.EnableEvents = True

End Sub

示例表结构

【问题讨论】:

  • 1.这是codereview.stackexchange.com 的一个更好的问题 2. 当您这样做时,请勿张贴您的代码和示例数据的图片。将代码和数据直接粘贴到帖子中,然后突出显示它们并按 Ctrl-k 进行格式化。
  • 请直接在此处发布代码。然后我就可以运行它了。您可以尝试在两部分之间放置一个 msgbox,看看第二部分是否比第一部分慢。我认为这是正确的,因为您删除了行,然后 Excel 需要移动很多单元格。
  • 我投票结束这个问题,因为这个问题属于codereview.stackexchange.com
  • @ScottCraner - 从截图来看,这不是工作代码。行删除循环正在向后运行(或根据您的观点以错误的方向运行)。
  • @Comintern 老实说,我按照他的描述说代码正在运行,我只是粗略地查看了代码。

标签: excel vba


【解决方案1】:

因为我提供了错误信息,说明应该在哪里发布。

以下代码几乎可以立即执行您想要的操作。

我使用数组来限制与工作表的交互次数。

Sub foo5()
Dim ws As Worksheet
Dim rng() As Variant
Dim oarr() As Variant
Dim i&, j&, k&


Set ws = ThisWorkbook.Worksheets("Sheet19") 'Change to your sheet
With ws
    rng = .Range("A1", .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft))).Value
    ReDim oarr(1 To Application.WorksheetFunction.CountA(rng), 1 To 1)
    k = 1
    For i = LBound(rng, 1) To UBound(rng, 1)
        For j = LBound(rng, 2) To UBound(rng, 2)
            If rng(i, j) <> "" Then
                oarr(k, 1) = rng(i, j)
                k = k + 1
            End If
        Next j
    Next i
    .Range("A1", .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft))).Clear
    .Range("A1").Resize(UBound(oarr), 1).Value = oarr
End With
End Sub

【讨论】:

  • 工作代码相比非工作代码绝对是效率的提升!
  • @Scott Craner 我只是尝试运行它。虽然代码连续运行,但在第 5304 行之后,列被分配了 N/A 值,而我应该有大约 117000 个条目。
  • @ForwardEd 是的,我同意!!
  • @zanwigz 编辑对您有用吗?我刚刚在 484 x 484 网格上试了一下,不到一秒。如果有效,请单击答案旁边的复选标记标记为正确。
  • @ScottCraner 恐怕它仍然不适合我。现在,它将第二列向下移动到第一列下方,然后代码结束。