我在包含许多列的Excel电子表格中有两列。我想合并这两列,但它们在工作表中的位置可能会有所不同。这意味着我需要利用第一行列标题来确定要连接哪两列。我希望将结果添加为工作表中的下一列。
例如,如果“Brand”,“Line”和“Product”在第1行作为列标题,则宏应在“Brand”中搜索该值并将其与“Model”中的值连接并放入导致工作表中的插入列(在这种情况下为D,但可能会根据列数更改)。我不能使用列或单元格引用,因为Brand和Model列的位置可能会更改,以及列数:
A | C | ç|
品牌|线|型号|
宾得|摄像机| K-30 |
本田|汽车|雅阁|
苹果|计算机| MacBook Air |
这是我尝试过的:
Sub Insrt()
Dim Model As Range
Dim Brand As Range
Dim LastRow As Long
Set Brand = Rows(1).Find(what:="Brand", LookIn:=xlValues, lookat:=xlWhole)
Set Model = Rows(1).Find(what:="Model", LookIn:=xlValues, lookat:=xlWhole)
If Found Is Nothing Then Exit Sub
LastRow = Cells(Rows.Count, Brand.Column).End(xlUp).Row
Model.Offset(, 1).EntireColumn.Insert
Cells(1, Model.Column + 1).Value = "Concatenated_Value"
Range(Cells(2, Model.Column + 1), Cells(LastRow, Model.Column + 1)).Formula = "=A2&C2"
End Sub
这种方法的问题在于我的公式是专门连接A列和A列。 C.然而,品牌和模型可能不会每次都出现在这些特定的列中 - 将来,它们可能会转移位置。我如何改进这一点,以便我没有明确地调用列A和C,而是使用列标题?
答案 0 :(得分:2)
我喜欢使用索引/匹配:
=F2 & " " &INDEX(A:C,MATCH(F2,A:A,0),MATCH("Model",1:1,0))
无论在哪里"型号"最终它会找到正确的列。
对于VBA。将公式更改为
"=" & Cells(2,brand.column).address(0,0) & "&" & Cells(2,model.column).address(0,0)
答案 1 :(得分:2)
尝试:
=HLOOKUP("Brand",A:C,ROW(),0) & " " & HLOOKUP("Model",A:C,ROW(),0)
答案 2 :(得分:0)
我在编辑的原始问题中修改了代码。
1-选项明确总是一个好主意。
2-考虑了2列标题搜索,更多DRY,特别是如果需要添加更多列以供查找。
2.a-此外,如果找不到,那么'测试没有工作,至少不在我的盒子上。即使它有效,它也没有给出任何信息。无声失败可能没问题,但往往不行。现在任何未找到的标题都会给出一条消息。
2.b-在Find()中添加了MatchCase:= True可能不是想要的改变,但确实显示为什么DRY代码(不要重复自己)有所帮助。如果您不喜欢这种变化很酷,您只需编辑一个地方即可将其更改回来,而不是为每个标题编辑一个地方编辑一个地方,而不是2,3或4个地方。
3-一个答案有片段' Cells(2,brand.column)。地址(0,0)'但Range对象上的Address()方法以大写A开头,但Excel ADDRESS函数全部大写。 ADDRESS函数文档说ADDRESS(0,0)是一个OK调用但是Range对象docs上的Address(0,0)方法说两个0值是Address()看到的变体为True或不是。
我修改为.Address(RowAbsolute:= False)所以不必将0理解为False,我们也希望ColumnAbsolute为True,这是默认值。我们想要一个绝对的,一个相对的,所以当编码地址(0,0)
时它们都是相同的4-变量Formula9仅用于简化调试。它可以在调试后编辑出来。另一方面,重复如何分配' Cells(2,Brand.Column)。地址(RowAbsolute:= False)'
所以也许是一个函数来分解' Cells(x,y).Address(RowAbsolute:= False)'会更干。
要留下多少个临时变量,要使代码更多DRY的分解是判断调用。
Option Explicit
Function FindOrMsg(toFind As String) As Range
Dim Rtn As Range
Set Rtn = Rows(1).Find(what:=toFind, LookIn:=xlValues, _
lookat:=xlWhole, MatchCase:=True)
Set FindOrMsg = Rtn
If Rtn Is Nothing Then MsgBox "Header '" & toFind & "' not found"
End Function
Sub Macro1()
Dim Model As Range
Dim Brand As Range
Dim LastRow As Long
Set Brand = FindOrMsg("Brand")
Set Model = FindOrMsg("Model")
If (Brand Is Nothing) Or (Model Is Nothing) Then Exit Sub
LastRow = Cells(Rows.Count, Brand.Column).End(xlUp).Row
Model.Offset(, 1).EntireColumn.Insert
Cells(1, Model.Column + 1).Value = "Concatenated_Value"
Dim Formula9
Formula9 = "=" & Cells(2, Brand.Column).Address(RowAbsolute:=False) & "&" _
& Cells(2, Model.Column).Address(RowAbsolute:=False) & ""
Range(Cells(2, Model.Column + 1), Cells(LastRow, Model.Column + 1)).Formula = Formula9
End Sub