3

我在 VBA for Excel 中创建了一个工具,它可以根据许多标准分析我们收到的 .xlsx 文件。其中之一是数据集中的空单元格的数量。但不幸的是,我注意到我们收到的许多文件包含的单元格中包含零长度字符串,这些单元格被“错误地”计为非空单元格。

如果我能够从文件中删除这些,这实际上对整个过程非常有益。

我已经用谷歌搜索了很多这个问题,但到目前为止我能找到的唯一解决方案是遍历工作表中的所有单元格(我也尝试过常量,并且还使用 Find 来查找所有 zls)。这不是很有效,因为工作表中包含大量数据。编辑:我也尝试过 UsedRange.values = UsedRange.values 方法,但这会删除我需要的前导零。

我还发现这是可行的(-@- 是一个随机字符串,极不可能是我数据中的单个单元格,如果它在那里,可以删除):

ws.UsedRange.Replace what:=vbNullString, replacement:="-@-", _
                            lookat:=xlWhole, MatchCase:=False
ws.UsedRange.Replace what:="-@-", replacement:="", _
                            lookat:=xlWhole, MatchCase:=False

但如果我只使用单个替换它不会:

ws.UsedRange.Replace what:=vbNullString, replacement:="", _
                            lookat:=xlWhole, MatchCase:=False

第一个没问题,但是有很多问题:

  1. 耗时是单次更换的两倍
  2. 它是否已经崩溃或继续工作并不总是很清楚
  3. 如果它确实崩溃了,我会留下一些包含 -@- 的单元格,这并不总是很明显,并且该工具应该可以被无法理解 VBA 的人使用。

所以我的问题:

  1. 有没有办法只使用一个替换来做到这一点?为什么替换与双重替换一起使用,而不是单一替换?
  2. 如果第一个是不可能的,那么如果代码崩溃,有没有办法“回滚”替换?
  3. 有没有一种方法可以更新状态栏以显示替换的程度以证明代码正在运行(就像在 Excel 本身中运行替换时一样)?
  4. 还是有更好的方法来完成这一切?

提前致谢!

编辑:不幸的是,由于正在处理数据,我需要保留格式,包括前导零

编辑:这是我正在查看的数据类型的示例。我想替换零长度字符串(它们是没有值的非空白单元格),因此它们是一个真正的空白单元格。

包含零长度字符串的表

4

3 回答 3

0

您可以拥有带有返回空字符串的公式的单元格或带有空字符串常量的单元格。清除第二种细胞:

Sub KillNullConstants()
    Dim cell As Range, Konstants As Range, rng As Range
    Set Konstants = ActiveSheet.UsedRange.Cells.SpecialCells(xlCellTypeConstants)
    Set rng = Nothing
    For Each cell In Konstants
        If Len(cell) = 0 Then
            If rng Is Nothing Then
                Set rng = cell
            Else
                Set rng = Union(rng, cell)
            End If
        End If
    Next cell

    If Not rng Is Nothing Then
        rng.ClearContents
    End If
End Sub

要清除返回空字符串的公式单元格,只需更改SpecialCells代码行。

于 2019-05-07T12:11:52.197 回答
0

我知道这也是一个循环,但也许是一种更快的方法:

前:

在此处输入图像描述

在示例数据上运行此代码:

Dim X As Double

Option Explicit

Sub Test()

Application.ScreenUpdating = False
Application.Calculation = xlManual

With ActiveWorkbook.Sheets(1).Range("A1:C7")
    For X = 1 To 3
        .AutoFilter Field:=X, Criteria1:=""
        .Columns(X).Offset(1, 0).SpecialCells(xlCellTypeVisible).Clear
    Next X
    .AutoFilter
End With

Application.Calculation = xlAutomatic
Application.ScreenUpdating = True

End Sub

后:

在此处输入图像描述

于 2019-05-07T13:15:43.653 回答
0

将工作表读入 ADO 记录集,然后将记录集复制到新工作表似乎可以解决此问题。试试这个 VBA 代码:

Sub copy_data()

Dim cn As Object
Set cn = CreateObject("ADODB.Connection")

With cn
    .Provider = "Microsoft.ACE.OLEDB.12.0"
    .ConnectionString = "Data Source=" & ThisWorkbook.FullName & ";" & _
        "Extended Properties=""Excel 12.0 Macro;IMEX=1;HDR=YES"";"
    .Open
End With

Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")

rs.Open "SELECT * FROM [Sheet1$];", cn

Dim i As Integer
Dim fld As Object

With ThisWorkbook.Worksheets("Sheet2")
    .UsedRange.ClearContents

    i = 0
    For Each fld In rs.Fields
        i = i + 1
        .Cells(1, i).Value = fld.Name
    Next fld

    .Cells(2, 1).CopyFromRecordset rs
    .UsedRange.Columns.AutoFit
End With

rs.Close
cn.Close

End Sub

笔记:

  • 更改代码中的工作表名称以匹配您正在使用的工作表名称。您必须在$您使用的工作表名称之后放置一个符号 rs.Open。如果你的工作表被称为“数据”,那么你会放 rs.Open "SELECT * FROM [Data$];", cn
  • 在连接字符串扩展属性中,HDR=YES 用于指定数据有标题。如果某些列名包含某些字符,ADO 可能会更改它们 - 主要是.通常会被字符替换的#字符

潜在问题:

  • 您的数据需要大致采用表格格式 - 即第 1 行中的列名,每个列名下方的数据值
  • 数据中的任何公式都将转换为值
  • 单元格格式不会被复制 - 但格式化为文本的数字将保留为文本,因此将保留前导零
  • 任何超过 255 个字符的单元格值文本都可能被截断为 255 个字符(如果需要,可以解决此问题)

根据您的数据,使用 ADO 可能会产生比它解决的问题更多的问题

于 2019-05-08T01:18:30.890 回答