Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 删除空白单元格-146459行_Vba_Excel_Powerpivot - Fatal编程技术网

Vba 删除空白单元格-146459行

Vba 删除空白单元格-146459行,vba,excel,powerpivot,Vba,Excel,Powerpivot,我希望你能在这个问题上帮助我 我有一个包含146459行的Excel文件,我需要删除空白单元格以统一数据。以下是我的意思: 当我选择所有空格时,我的笔记本电脑大约需要2分钟,但当我尝试从一列或多列中删除单元格并向上移动时,Excel冻结,什么也没有发生。我已经离开我的笔记本电脑一个多小时了,我没有任何结果 你知道是否有办法做到这一点,或者是否可以实施任何替代方案 提前谢谢 通过单元循环需要很长的时间,即使使用Union优化。 下面的代码是在模拟数据集上测试的,5列x 200000条记录,在5.

我希望你能在这个问题上帮助我

我有一个包含146459行的Excel文件,我需要删除空白单元格以统一数据。以下是我的意思:

当我选择所有空格时,我的笔记本电脑大约需要2分钟,但当我尝试从一列或多列中删除单元格并向上移动时,Excel冻结,什么也没有发生。我已经离开我的笔记本电脑一个多小时了,我没有任何结果

你知道是否有办法做到这一点,或者是否可以实施任何替代方案


提前谢谢

通过单元循环需要很长的时间,即使使用Union优化。 下面的代码是在模拟数据集上测试的,5列x 200000条记录,在5.5秒内完成

设置: 假设您的源数据在名为“source”的工作表上的范围为“A1:E200000”,并且您希望在名为“Target”的工作表上的干净数据在类似的范围内

代码:

选项显式
子删除\u空\u单元格()
暗光源作为量程
作为射程的弱小目标
作为整数的Dim i
Set Source=thiswook.Sheets(“Source”).Range(“A1:E200000”)
设置目标=此工作簿.Sheets(“目标”).Range(“A1:E200000”)
对于i=1到Source.Columns.Count
清除列源.Columns(i),目标.Columns(i)
接下来我
端接头
子Clean_列(源作为范围,目标作为范围)
将遥感器作为对象
将XML作为对象
设置XML=CreateObject(“MSXML2.DOMDocument”)
XML.LoadXML Source.Value(xlRangeValueMSPersistXML)
Set rs=CreateObject(“ADODB.Recordset”)
开放式XML
rs.Filter=rs.Fields(0)。名称和“null”
Target.CopyFromRecordset rs
端接头
工作原理: Sub Remove_Empty_Cells按列循环源范围,并调用Sub“Clean_Column”从提供的列中删除空单元格

Clean_Column使用MSXML2.DOMDocument对象将所有列单元格加载到ADO记录集中。然后过滤记录集中的非空行,并将结果复制到目标列。所有这些操作在VBA中都非常快速

理想情况下,我希望一次将整个范围加载到记录集中,但不幸的是,VBA函数CopyFromRecordset不允许逐个字段粘贴记录集。因此,我们必须一列一列地加载数据(如果有人知道一种更好的方法,我很乐意看到)

有几个注意事项:

  • 出于某种原因(?),第一列复制时不带标题,而所有连续列复制时带标题。然后必须插入第一列的标题(手动或使用VBA)
  • 我假设每列中非空单元格的数量是相同的,否则清理的记录将无法排列(如果是这种情况,则会出现更大的问题) [编辑]: 另一种解决方案,使用阵列实现。在不到1秒的时间内清除了相同的数据集5x 200000和40000条有效记录。它可以进一步优化,我只是制作了一个快速演示的原型

    Sub Remove_Empty_Cells()
    Dim Source_Data()   As Variant
    Dim Clean_Data()    As Variant
    Dim Source_Range    As Range
    Dim Target_Range    As Range
    Dim Column_Count    As Long
    Dim Row_Count       As Long
    Dim i               As Long
    Dim j               As Long
    Dim k               As Long
    
        Set Source_Range = ThisWorkbook.Sheets("Source").Range("A1:E200000")
    
        Column_Count = Source_Range.Columns.Count
        Row_Count = Source_Range.Rows.Count
    
        ReDim Source_Data (1 To Row_Count, 1 To Column_Count)
        ReDim Clean_Data (1 To Row_Count, 1 To Column_Count)
    
        Source_Data = Source_Range
    
        For j = 1 To Column_Count
            k = 1
            For i = 1 To Row_Count
                If Source_Data(i, j) <> "" Then
                    Clean_Data(k, j) = Source_Data(i, j)
                    k = k + 1
                End If
            Next i
        Next j
    
        Set Target_Range = ThisWorkbook.Sheets("Target").Range("A1").Resize(Row_Count, Column_Count)
        Target_Range = Clean_Data
    
    End Sub
    
    Sub-Remove_Empty_Cells()
    Dim Source_Data()作为变量
    Dim Clean_Data()作为变量
    变暗源_范围作为范围
    变暗目标范围作为范围
    Dim列\u计数为长
    变暗行\按长计数
    我想我会坚持多久
    Dim j尽可能长
    暗k一样长
    设置Source_Range=thiswook.Sheets(“Source”).Range(“A1:E200000”)
    Column\u Count=源\u Range.Columns.Count
    行\计数=源\范围.Rows.Count
    重拨源数据(1到行计数,1到列计数)
    重拨清除数据(1到行计数,1到列计数)
    源\数据=源\范围
    对于j=1到列_计数
    k=1
    对于i=1的行数
    如果源_数据(i,j)“,则
    清洁_数据(k,j)=源_数据(i,j)
    k=k+1
    如果结束
    接下来我
    下一个j
    设置目标范围=此工作簿。工作表(“目标”)。范围(“A1”)。调整大小(行数、列数)
    目标范围=清除数据
    端接头
    
    即使使用Union优化,在单元格中循环也需要很长时间。 下面的代码是在模拟数据集上测试的,5列x 200000条记录,在5.5秒内完成

    设置: 假设您的源数据在名为“source”的工作表上的范围为“A1:E200000”,并且您希望在名为“Target”的工作表上的干净数据在类似的范围内

    代码:

    选项显式
    子删除\u空\u单元格()
    暗光源作为量程
    作为射程的弱小目标
    作为整数的Dim i
    Set Source=thiswook.Sheets(“Source”).Range(“A1:E200000”)
    设置目标=此工作簿.Sheets(“目标”).Range(“A1:E200000”)
    对于i=1到Source.Columns.Count
    清除列源.Columns(i),目标.Columns(i)
    接下来我
    端接头
    子Clean_列(源作为范围,目标作为范围)
    将遥感器作为对象
    将XML作为对象
    设置XML=CreateObject(“MSXML2.DOMDocument”)
    XML.LoadXML Source.Value(xlRangeValueMSPersistXML)
    Set rs=CreateObject(“ADODB.Recordset”)
    开放式XML
    rs.Filter=rs.Fields(0)。名称和“null”
    Target.CopyFromRecordset rs
    端接头
    
    工作原理: Sub Remove_Empty_Cells按列循环源范围,并调用Sub“Clean_Column”从提供的列中删除空单元格

    Clean_Column使用MSXML2.DOMDocument对象将所有列单元格加载到ADO记录集中。然后过滤记录集中的非空行,并将结果复制到目标列。所有这些操作在VBA中都非常快速

    理想情况下,我希望一次将整个范围加载到记录集中,但不幸的是,VBA函数CopyFromRecordset不允许逐个字段粘贴记录集。因此,我们必须一列一列地加载数据(如果有人知道一种更好的方法,我很乐意看到)

    有几个注意事项:

  • 出于某种原因(?),第一列复制时不带标题,而所有连续列复制时带标题。那么第一列呢
    Sub Remove_Empty_Cells()
    Dim Source_Data()   As Variant
    Dim Clean_Data()    As Variant
    Dim Source_Range    As Range
    Dim Target_Range    As Range
    Dim Column_Count    As Long
    Dim Row_Count       As Long
    Dim i               As Long
    Dim j               As Long
    Dim k               As Long
    
        Set Source_Range = ThisWorkbook.Sheets("Source").Range("A1:E200000")
    
        Column_Count = Source_Range.Columns.Count
        Row_Count = Source_Range.Rows.Count
    
        ReDim Source_Data (1 To Row_Count, 1 To Column_Count)
        ReDim Clean_Data (1 To Row_Count, 1 To Column_Count)
    
        Source_Data = Source_Range
    
        For j = 1 To Column_Count
            k = 1
            For i = 1 To Row_Count
                If Source_Data(i, j) <> "" Then
                    Clean_Data(k, j) = Source_Data(i, j)
                    k = k + 1
                End If
            Next i
        Next j
    
        Set Target_Range = ThisWorkbook.Sheets("Target").Range("A1").Resize(Row_Count, Column_Count)
        Target_Range = Clean_Data
    
    End Sub
    
    Option Explicit
    
    Sub delBlanks()
        Dim i As Long, j As Long, k As Long, arr As Variant, vals As Variant
        Dim s As Double, e As Double, c As Long
    
        s = Timer
    
        With Worksheets("sheet6")
            If .AutoFilterMode Then .AutoFilterMode = False
    
            'data validity check
            c = Application.CountA(.Columns(1))
            For j = 2 To 5
                If c <> Application.CountA(.Columns(j)) Then Exit For
            Next j
            If j <= 5 Then
                Debug.Print "GIGO, waste of time to continue"
                Exit Sub
            End If
    
            'collect offset values
            vals = .Range(.Cells(2, "A"), .Cells(.Rows.Count, "E").End(xlUp)).Value2
            ReDim arr(LBound(vals, 1) To UBound(vals, 1), _
                      LBound(vals, 2) To UBound(vals, 2))
    
            'loop through array coolating A"E to a single row
            i = LBound(vals, 1)
            k = LBound(arr, 1)
            Do
                For j = LBound(vals, 2) To UBound(vals, 2)
                    Do While vals(i, j) = vbNullString: i = i + 1: Loop
                    arr(k, j) = vals(i, j)
                Next j
                i = i + 1: k = k + 1
            Loop Until i > UBound(vals, 1)
    
            'put data back on worksheet
            .Cells(2, "A").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
            .Cells(2, "C").Resize(UBound(arr, 1), 1).NumberFormat = "dd/mm/yyyy"
        End With
    
        e = Timer
    
        Debug.Print c - 1 & " records in " & UBound(vals, 1) & _
                    " rows collated in " & Format((e - s), "0.000") & " seconds"
    End Sub
    
    30000 records in 157500 rows collated in 0.984 seconds
    
    Sub fillBlanks()
        Dim i As Long, j As Long, k As Long, arr As Variant, vals As Variant
    
        vals = Array("to: ""someone"" <someone@null.com", "from: ""no one"" <no_one@null.com", _
                     Date, "\i\m\p\o\r\t\a\n\c\e\: 0", "subject: something nothing")
    
        ReDim arr(1 To 6, 1 To 5)
    
        With Worksheets("sheet6")
            .Cells(1, 1).CurrentRegion.Offset(1, 0).Clear
            For k = 1 To 30000
                j = 0
                For i = LBound(arr, 2) To UBound(arr, 2)
                    If i = 2 And Not CBool(k Mod 4) Then j = j + 1
                    If i = 4 Then
                        arr(i + j, i) = Format(k, vals(i - 1))
                    Else
                        arr(i + j, i) = vals(i - 1)
                    End If
                Next i
                .Cells(.Rows.Count, 5).End(xlUp).Offset(1, -4).Resize(UBound(arr, 1), UBound(arr, 2)) = arr
                ReDim arr(1 To 6, 1 To 5)
            Next k
        End With
    End Sub