Excel 使用宏从多个列中提取唯一值
我在a中有一个代码列表,在B和C中有图像链接 我想做的是删除重复项并将唯一链接安排在一列中,并为它们提供一个序列名,在图像链接1之前不增加代码_1,在链接2之前增加代码_2,如图所示 我试图用这段代码来删除重复的内容,但对如何将名称放在链接之前一无所知Excel 使用宏从多个列中提取唯一值,excel,vba,Excel,Vba,我在a中有一个代码列表,在B和C中有图像链接 我想做的是删除重复项并将唯一链接安排在一列中,并为它们提供一个序列名,在图像链接1之前不增加代码_1,在链接2之前增加代码_2,如图所示 我试图用这段代码来删除重复的内容,但对如何将名称放在链接之前一无所知 Sub tgr() Dim wb As Workbook Dim wsDest As Worksheet Dim rData As Range Dim rArea As Range Dim aData
Sub tgr()
Dim wb As Workbook
Dim wsDest As Worksheet
Dim rData As Range
Dim rArea As Range
Dim aData As Variant
Dim i As Long, j As Long
Dim hUnq As Object
'Prompt to select range. Uniques will be extracted from the range selected.
'Can select a non-contiguous range by holding CTRL
On Error Resume Next
Set rData = Application.InputBox("Select range of names where unique names will be extracted:", "Data Selection", Selection.Address, Type:=8)
On Error GoTo 0
If rData Is Nothing Then Exit Sub 'Pressed cancel
Set hUnq = CreateObject("Scripting.Dictionary")
For Each rArea In rData.Areas
If rArea.Cells.Count = 1 Then
ReDim aData(1 To 1, 1 To 1)
aData(1, 1) = rArea.Value
Else
aData = rArea.Value
End If
For i = 1 To UBound(aData, 1)
For j = 1 To UBound(aData, 2)
If Not hUnq.Exists(aData(i, j)) And Len(Trim(aData(i, j))) > 0 Then hUnq(Trim(aData(i, j))) = Trim(aData(i, j))
Next j
Next i
Next rArea
Set wb = rData.Parent.Parent 'First parent is the range's worksheet, second parent is the worksheet's workbook
Set wsDest = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
wsDest.Range("A1").Resize(hUnq.Count).Value = Application.Transpose(hUnq.Items)
End Sub
此自定义VBA函数将创建获取SKU代码所需的结果。我将其分解,以展示如何获得每个职位
Function Drop_Bucks(inputText As String) As String
Dim beginSpot As Long, endSpot As Long
'Finds last /
beginSpot = InStrRev(inputText, "/", -1, vbTextCompare) + 1
'Finds jpg
endSpot = InStrRev(inputText, ".jpg", -1, vbTextCompare)
Drop_Bucks = Replace(Mid(inputText, beginSpot, endSpot - beginSpot), "-", "_")
End Function
作为后续工作,您还可以创建不带VBA的sku。如果将此公式放入单元格c4
,sku放入单元格d4
。它应该没有宏
=代用词(左代用词(右代用词(d4,“/”,REPT(“?”,999)),999),“?”,“.jpg”,REPT(“?”,999)),999),“?”,“-”,“”)
这将构建一个包含所有重复项和所有重复项的列表。然后,它将使用函数
Range.removedupplicates
删除SKU代码的重复项,并将其与范围内的URL相结合
选项显式
Sub Test()
Dim oCurSourceSheet As Worksheet
Set oCurSourceSheet = Sheet1 ' What sheet is your Source Data on?
Dim oSourceRow As Long ' Which Row/Column does your data start on?
oSourceRow = 2 ' First Row of First "Link"
Dim oSourceCol As Long
oSourceCol = 2 ' First Column of First "Link"
Dim oOutputRange As Range
Set oOutputRange = Sheet1.Range("A10") ' What Sheet/Cell do you want the output to start on/in?
Dim oCurRow As Long ' Row counter for Output
oCurRow = 1
Dim oCurSourceRow As Long
Dim oCurSourceCol As Long
For oCurSourceRow = oSourceRow To oCurSourceSheet.UsedRange.Rows.Count
For oCurSourceCol = oSourceCol To oCurSourceSheet.UsedRange.Columns.Count
oOutputRange.Cells(oCurRow, 1) = oCurSourceSheet.Cells(oCurSourceRow, 1) & "_" & oCurSourceCol - 1
oOutputRange.Cells(oCurRow, 2) = oCurSourceSheet.Cells(oCurSourceRow, oCurSourceCol)
oCurRow = oCurRow + 1
Next
Next
'Reize range from output's starting cell & remove duplicates
Set oOutputRange = oOutputRange.Resize(oCurRow - 1, 2)
oOutputRange.RemoveDuplicates Columns:=Array(1, 2)
End Sub
这可能会帮助您:
Option Explicit
Sub TEST()
Dim LastRow As Long, i As Long, LastRow2 As Long
Dim arr As Variant
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("$A$2:$C$" & LastRow).RemoveDuplicates Columns:=Array(1, 2, 3), Header:=xlNo
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arr = .Range("A2:C" & LastRow)
For i = LBound(arr) To UBound(arr)
LastRow2 = .Cells(.Rows.Count, "E").End(xlUp).Row
.Range("E" & LastRow2 + 1).Value = arr(i, 1) & "_1"
.Range("F" & LastRow2 + 1).Value = arr(i, 2)
Next i
For i = LBound(arr) To UBound(arr)
LastRow2 = .Cells(.Rows.Count, "E").End(xlUp).Row
.Range("E" & LastRow2 + 1).Value = arr(i, 1) & "_2"
.Range("F" & LastRow2 + 1).Value = arr(i, 3)
Next i
End With
End Sub
请试试这个:我修改了你的代码。字典的使用就像一个避免重复值的工具(由于它的存在…)。一切都在内存中运行,速度应该非常快:
Option Base 1
Sub tgr_bis()
Dim wb As Workbook, rData As Range, wsDest As Worksheet, rArea As Range
Dim aData As Variant, aDataSorted() As String
Dim i As Long, hUnq As Scripting.Dictionary, nrColumns As Long
On Error Resume Next
Set rData = Application.InputBox("Select range of names where unique names will be extracted:", "Data Selection", Selection.Address, Type:=8)
On Error GoTo 0
If rData Is Nothing Then Exit Sub 'Pressed cancel
'Debug.Print rData.Columns.Count: Stop
If rData.Columns.Count > 6 Then MsgBox "More then 6 columns..." & vbCrLf & _
"Please select only six columns and run the procedure again", vbInformation, _
"Too many columns": Exit Sub
nrColumns = rData.Columns.Count
Set hUnq = CreateObject("Scripting.Dictionary")
For Each rArea In rData.Areas
If rArea.Cells.Count = 1 Then
ReDim aData(1 To 1, 1 To 1)
aData(1, 1) = rArea.value
Else
aData = rArea.value
End If
ReDim aDataSorted(nrColumns, 1)
Dim k As Long
k = 1
For i = 1 To UBound(aData, 1)
If Not hUnq.Exists(aData(i, 1)) And Len(Trim(aData(i, 1))) > 0 Then
aDataSorted(1, k) = aData(i, 1): aDataSorted(2, k) = aData(i, 2): aDataSorted(3, k) = aData(i, 3)
Select Case nrColumns
Case 4
If aData(i, 4) <> "" Then aDataSorted(4, k) = aData(i, 4)
Case 5
If aData(i, 4) <> "" Then aDataSorted(4, k) = aData(i, 4)
If aData(i, 5) <> "" Then aDataSorted(5, k) = aData(i, 5)
Case 6
If aData(i, 4) <> "" Then aDataSorted(4, k) = aData(i, 4)
If aData(i, 5) <> "" Then aDataSorted(5, k) = aData(i, 5)
If aData(i, 6) <> "" Then aDataSorted(6, k) = aData(i, 6)
Case > 6
MsgBox "Too many selected columns!": Exit Sub
End Select
k = k + 1
ReDim Preserve aDataSorted(nrColumns, k)
hUnq(Trim(aData(i, 1))) = Trim(aData(i, 1))
End If
Next i
Next rArea
'Process the new array in order to be tansformed in what is needed:
Dim finalCol() As String
k = k - 1: Z = 1
ReDim finalCol(2, Z)
Dim lngIndex As Long
Dim totalRows As Long
For i = 1 To k
lngIndex = 1
finalCol(1, Z) = aDataSorted(1, i) & "_" & lngIndex: lngIndex = lngIndex + 1: _
finalCol(2, Z) = aDataSorted(2, i): totalRows = totalRows + 1
Z = Z + 1: ReDim Preserve finalCol(2, Z)
finalCol(1, Z) = aDataSorted(1, i) & "_" & lngIndex: lngIndex = lngIndex + 1: _
finalCol(2, Z) = aDataSorted(3, i): totalRows = totalRows + 1
Z = Z + 1: ReDim Preserve finalCol(2, Z)
If nrColumns < 4 Then GoTo EndLoop
If aDataSorted(4, i) <> "" Then finalCol(1, Z) = aDataSorted(1, i) & "_" & lngIndex: _
lngIndex = lngIndex + 1: finalCol(2, Z) = aDataSorted(4, i): totalRows = totalRows + 1: _
Z = Z + 1: ReDim Preserve finalCol(2, Z)
If nrColumns < 5 Then GoTo EndLoop
If aDataSorted(5, i) <> "" Then finalCol(1, Z) = aDataSorted(1, i) & "_" & lngIndex: _
lngIndex = lngIndex + 1: finalCol(2, Z) = aDataSorted(5, i): totalRows = totalRows + 1: _
Z = Z + 1: ReDim Preserve finalCol(2, Z)
If nrColumns < 6 Then GoTo EndLoop
If aDataSorted(6, i) <> "" Then finalCol(1, Z) = aDataSorted(1, i) & "_" & lngIndex: _
lngIndex = lngIndex + 1: finalCol(2, Z) = aDataSorted(6, i): totalRows = totalRows + 1: _
Z = Z + 1: ReDim Preserve finalCol(2, Z)
EndLoop:
Next i
Set wb = rData.Parent.Parent
Set wsDest = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
wsDest.Range("A1:B" & totalRows) = Application.Transpose(finalCol)
End Sub
选项库1
分包商
将wb作为工作簿,rData作为范围,wsDest作为工作表,rArea作为范围
Dim aData作为变量,aDataSorted()作为字符串
Dim i和Scripting一样长,hUnq和Scripting一样长。Dictionary,nr列和Scripting一样长
出错时继续下一步
Set rData=Application.InputBox(“选择将提取唯一名称的名称范围:”,“数据选择”,选择.地址,类型:=8)
错误转到0
如果rData为空,则退出“按取消”
'Debug.Print rData.Columns.Count:停止
如果rData.Columns.Count>6,则MsgBox“超过6列…”&vbCrLf&_
“请仅选择六列,然后再次运行该过程”,vbInformation_
“列太多”:退出Sub
nrColumns=rData.Columns.Count
Set hUnq=CreateObject(“Scripting.Dictionary”)
对于rData.区域中的每个稀有物种
如果rArea.Cells.Count=1,则
雷迪姆数据(1对1,1对1)
aData(1,1)=稀有值
其他的
aData=稀有值
如果结束
ReDim aDataSorted(第1列)
暗k一样长
k=1
对于i=1到UBound(aData,1)
如果不存在hUnq(aData(i,1))和Len(Trim(aData(i,1)))>0,那么
aDataSorted(1,k)=aData(i,1):aDataSorted(2,k)=aData(i,2):aDataSorted(3,k)=aData(i,3)
选择Case列
案例4
如果aData(i,4)“,那么aDataSorted(4,k)=aData(i,4)
案例5
如果aData(i,4)“,那么aDataSorted(4,k)=aData(i,4)
如果aData(i,5)”,那么aDataSorted(5,k)=aData(i,5)
案例6
如果aData(i,4)“,那么aDataSorted(4,k)=aData(i,4)
如果aData(i,5)”,那么aDataSorted(5,k)=aData(i,5)
如果aData(i,6)”,那么aDataSorted(6,k)=aData(i,6)
案例>6
MsgBox“选择的列太多!”:退出子菜单
结束选择
k=k+1
雷迪姆保留自适应排序(NRK列)
hUnq(Trim(aData(i,1))=Trim(aData(i,1))
如果结束
接下来我
下一个稀有物种
'处理新阵列,以便转换所需内容:
将finalCol()设置为字符串
k=k-1:Z=1
雷迪姆金融(2,Z)
暗指数和长指数一样
所有行的长度相同
对于i=1到k
lngIndex=1
finalCol(1,Z)=aDataSorted(1,i)和“”和lngIndex:lngIndex=lngIndex+1:_
finalCol(2,Z)=aDataSorted(2,i):totalRows=totalRows+1
Z=Z+1:ReDim保留最终目标(2,Z)
finalCol(1,Z)=aDataSorted(1,i)和“”和lngIndex:lngIndex=lngIndex+1:_
finalCol(2,Z)=aDataSorted(3,i):totalRows=totalRows+1
Z=Z+1:ReDim保留最终目标(2,Z)
如果nR列<4,则转到EndLoop
如果aDataSorted(4,i)“,则finalCol(1,Z)=aDataSorted(1,i)&“u”&lngIndex:_
lngIndex=lngIndex+1:finalCol(2,Z)=aDataSorted(4,i):totalRows=totalRows+1:_
Z=Z+1:ReDim保留最终目标(2,Z)
如果nR列数小于5,则转到EndLoop
如果aDataSorted(5,i)“,则finalCol(1,Z)=aDataSorted(1,i)&“u”&lngIndex:_
lngIndex=lngIndex+1:finalCol(2,Z)=aDataSorted(5,i):totalRows=totalRows+1:_
Z=Z+1:ReDim保留最终目标(2,Z)
如果nR列数小于6,则转到EndLoop
如果aDataSorted(6,i)“,则finalCol(1,Z)=aDataSorted(1,i)&“u”&lngIndex:_
lngIndex=lngIndex+1:finalCol(2,Z)=aDataSorted(6,i):totalRows=totalRows+1:_
Z=Z+1:ReDim保留最终目标(2,Z)
结束循环:
接下来我
设置wb=rData.Parent.Parent
设置wsDest=wb.Sheets.Add(后面:=wb.Sheets(wb.Sheets.Count))
wsDest.Range(“A1:B”和totalRows)=应用程序转置(finalCol)
端接头
'必须添加对“Microsoft脚本运行时”的引用。否则,您可以将hUnq声明为对象。。。
并且不要忘记在该代码所在模块的tot上设置选项库
。有必要使用构建初始代码的方式
编辑:我根据您的建议修改了代码,最多可以接受六列。恳求