我发现我工作的办公室花了数周时间手动浏览包含超过 500,000 行的数据库的 Excel 电子表格,以寻找符合特定条件的重复行。在研究之前不能简单地删除重复项,因为一个错误可能会导致生产损失数十万美元。我决定简单地标记它们并在这种情况下引用原始行将是最好的答案。所以我决定研究宏,看看使用简单的宏可以节省多少时间。我将此用作编程学习经验,因此请不要回答“这是一个 =function()”。
我写了一个宏并多次更改它都无济于事(最新的在下面)。我想使用 String 变量,因为不知道在要检查的单元格中输入了什么。以下是我从该站点尝试、失败和学到的(?):
最初,我尝试声明一个变量,并将单元格中的值直接附加到它。例如Dim myString As String Set myString = Cells(x, x).Value
,我一直收到对象错误。感谢迈克尔在这里的回应,我了解到您必须使用Range
变量才能使用Set
.
我的下一个问题是“类型不匹配”错误。我正在尝试分配一个存储变量并将其与另一个存储变量进行比较,我确定这是导致问题的原因。我最初尝试过Dim myRange As Range, myString As String Set myRange = Cells(x, x).Value myString = myRange
。这显然不起作用,所以我尝试使用CStr()
“更改为字符串”函数将 Range 变量转换为我想要的 String 变量。这就是我被困的地方。
Sub Duplicate()
'Declare the variables
Dim NSNrange, PNrange, KitIDrange As Range
Dim NSN, PN, KitID As String
Dim NSNCheck, PNCheck, KitIDCheck As String
Dim i, j, printColumn, rowCount As Integer
'Set which column we want to print duplicates on, and count the number of rows used
rowCount = ActiveSheet.UsedRange.Rows.Count
printColumn = 9
'Lets get started!
'Clear the duplicate list column for a fresh start
Columns(printColumn).EntireColumn.Delete
'Start on line 2, and grab the cell values for the NSN, Part number and kit ID.
For i = 2 To rowCount
Set NSNrange = Cells(i, 5).Value
Set PNrange = Cells(i, 7).Value
Set KitIDrange = Cells(i, 2).Value
'Change whatever is contained in those cells into a string and store them into their respective containers
NSN = CStr(NSNrange)
PN = CStr(PNrange)
KitID = CStr(KitIDrange)
'Now let's look through the rest of the sheet and find any others that match the 3 variables that we stored above
For j = 2 To rowCount
'To avoid needless checks, we'll check to see if it's already had a duplicate found. If so, we'll just skip to the next row
If Cells(j, printColumn).Value = "" Then
'If the print column is blank, we'll grab the 3 values from the current row to compare against the above variables
Set NSNrange = Cells(j, 5).Value
Set PNrange = Cells(j, 7).Value
Set KitIDrange = Cells(j, 2).Value
'Now we store the contents into their very own container
NSNCheck = CStr(NSNrange)
PNCheck = CStr(PNrange)
KitIDCheck = CStr(KitIDrange)
'Check the initial row with the current row to see if the contents match. If so, print which row it is duplicated on.
If NSN = NSNCheck And PN = PNCheck And KitID = KitIDCheck Then Cells(j, printColumn).Value = "Duplicated on row " & i
End If
Next j
Next i
MsgBox "Search Complete"
End Sub
正如您要求提供有关类型错误的评论。有很多地方可能会出现混淆
1)在同一行上执行多个声明的每一行,如下所示:
Dim NSNrange, PNrange, KitIDrange As Range
只有最后一个变量是明确类型声明的(在这种情况下为 a Range
)。其他是隐含的Variant
。所以,我已经通过并把它们放在了单独的行上,并按照我相信你的意思来声明它们。
2) 使用Activesheet
and,在其他地方,只是Cells
或Range
,它隐含地引用了Activesheet
,意味着如果您到那时更改了工作表,您可能不再引用您想要的工作表。因此,虽然我保留Activesheet
并使用了一个总体With Activesheet
声明,然后允许我说.Cells
或.Range
等等,但您应该将其更改为使用明确的工作表名称。
3)无论您在哪里使用Set
关键字,都期望您正在使用对象(例如 a Range
)。按照你的命名约定,我会说你的意思是
Set NSNrange = Cells(i, 5)
当你说
Set NSNrange = Cells(i, 5).Value
它将范围设置为另一个范围而不是单元格值。
4)我已将您的整数更改为多头。您正在处理的行可能超出Integer
类型可以处理的范围,因此您冒着溢出的风险。Long
更安全。
5)而不是Range
按如下方式进行转换
NSN = CStr(NSNrange)
其中范围的默认属性.Value
, 将被采用,因为你想要一个字符串,你可以放弃CStr
转换并只采用.Text
会给你你想要的字符串的属性。
6)""
我使用了比空字符串文字比较vbNullString
更快的分配和检查。
Option Explicit
Sub Duplicate()
Dim NSNrange As Range
Dim PNrange As Range
Dim KitIDrange As Range
Dim NSN As String
Dim PN As String
Dim KitID As String
Dim NSNCheck As String
Dim PNCheck As String
Dim KitIDCheck As String
Dim i As Long
Dim j As Long
Dim printColumn As Long
Dim rowCount As Long
With ActiveSheet
rowCount = .UsedRange.Rows.Count
printColumn = 9
.Columns(printColumn).EntireColumn.Delete
For i = 2 To rowCount
Set NSNrange = .Cells(i, 5)
Set PNrange = .Cells(i, 7)
Set KitIDrange = .Cells(i, 2)
NSN = NSNrange.Text
PN = PNrange.Text
KitID = KitIDrange.Text
For j = 2 To rowCount
If .Cells(j, printColumn).Value = vbNullString Then
Set NSNrange = .Cells(j, 5)
Set PNrange = .Cells(j, 7)
Set KitIDrange = .Cells(j, 2)
NSNCheck = NSNrange.Text
PNCheck = PNrange.Text
KitIDCheck = KitIDrange.Text
If NSN = NSNCheck And PN = PNCheck And KitID = KitIDCheck Then
.Cells(j, printColumn).Value = "Duplicated on row " & i
End If
End If
Next j
Next i
End With
MsgBox "Search Complete"
End Sub
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句