从已closures的工作簿填充正确的标题
我一直在解决这个问题一段时间,我有一个非常基本的版本工作,没有error handling。 我的目标是从macros观个人工作簿中运行这个macros。
我正在导入来自各种来源的pipe道分隔文本文件,而且标题中的格式都不匹配(有些提供者决定使用整个布局)。 有了这个问题,我创build了一个名为Reference(也称为Map)的Excel工作簿,其中包含传入的文件布局和标准化/更正的列名称格式。
对我来说好消息是,文件ID总是在A列。我有大约65个需要每个月处理的文件,所以我需要最小化所有可能的步骤,因此需要closures参考工作簿。
有了这个,我在网上环顾四周,将大部分解决scheme放在一起,根据位于A3中的ID拉入新的标题。 但仍然存在一个困境,有时A3上的ID将不会存在于参考工作簿上 – 我需要让vlookup下移到下一行,直到结果不等于#N / A或0或空白。
在这一点上,我得到了'Do Loop Until'来find第一个匹配的正确的行 – 完全无法使用任何后面的代码。
一旦vlookupfind一个具有现有ID的行,然后运行下面的代码片段填充剩余的标题。 下一步的唯一副作用是,由于某种原因,rID偏移+1行,如果最后一行不包含匹配的ID,则取消“直到执行循环”。
'> Populate remining headers For Each cell In rng1 cell.Value = ("=VLOOKUP(" & cID & rID & "," & map & "," & i & ",FALSE)") i = i + 1 Next
这是我迄今为止:
Sub DAc_lookup_headers() Dim wb1 As Workbook 'Current text/file Dim map As String 'reference Map Dim cID As String 'wb1 look up column A Dim rID As String 'wb1 starting row number Dim rng1 As Range 'wb1 Collection header range Dim i As Long 'Index number per cell in range Set wb1 = ActiveWorkbook Set rng1 = wb1.ActiveSheet.[A1:G1] map = ("'C:\Users\x165422\Desktop\New folder\[Reference.xlsx]Ref'!$A$1:$I$13") rID = 3 'Row where ID is - will increment + 1 if not found cID = "A" 'Column where ID is i = 3 'Starting vlookup Index number - to increment per cell in range '>Look for ID until value is found Do wb1.ActiveSheet.[a1].Value = ("=VLOOKUP(" & cID & rID & "," & map & "," & i & ",FALSE)") rID = rID + 1 Loop Until wb1.ActiveSheet.[a1].Text <> "#N/A" Or "0" '> Populate remining headers For Each cell In rng1 cell.Value = ("=VLOOKUP(" & cID & rID & "," & map & "," & i & ",FALSE)") i = i + 1 Next '> Convert to values With rng1 .Value = .Value End With End Sub
我会尽力帮助一下,因为你performance出努力去学习。 我会给你一些关于整体VBA编码的有用提示,以及你的问题。 请尽量记住它们。
-
读取代码很困难,因为你的variables命名不当。 在VBA中,单元格和它的值是有区别的。 在你的代码中你有
rng1
和rng2
。 我发现目前rng1
代表单元格的值,而rng2
– 单元格本身。 我不确定你是否故意这样做,但现在你会明白这一点。 如果你的意思是一个单元格本身,那么命名variablesrng2
是很好理解的。 但是,如果你指的是单元格的价值,那么命名variablesrng1
是有误导性的。 这只是为了能够更容易地阅读代码。 由于您将此variables定义为string
,我怀疑您希望它接收string
types的值。 所以,你应该把你的variables命名为与它的types有关的东西,例如以str...
或s...
开头的东西,这意味着这个variables是string
types的,例如strValue
或sID
。 最好的方法是使用str
,因为s
可能与single
types混淆(在VBA中也有这样的数据types)。 你应该把这个逻辑应用到你使用的每个variables上。 String –str...
,long –lng...
,integer –int...
,double –dbl...
,boolean –bln...
等等。一种types是特定的,您也可以在这里使用它。 这是object
types。 对象不仅仅是对象,它们被分解成许多不同的types,在你的代码中你也可以使用range
和workbook
对象。 您可以将它们命名为o...
或者obj...
,或者通常最好使用更具体的名称,例如rng...
(用于范围)或wb...
(用于工作簿)。 通常的数据typesvariables取值没有Set
子句,而对象总是需要Set
来关联一些实际的对象,比如范围,工作簿,工作表等。在你的代码中,我们看到wb2
variables是一个string
。 现在你知道,那不好。 所以,在这种情况下,如果你期望它是string
而不是range
并且总是使用这个命名约定,你应该重命名rng1
。 和wb2
。 -
总是使用
Option Explicit
作为代码模块中的最上面一行,在所有sub
节点之前。 这只是防止错别字。 而这实际上是一条不可或缺的路线。 我总是使用它,每个人都应该。 这样做后,我看到你的代码将不会运行,因为cell
variables没有定义。 使用Dim cell As Range
,因为单元格实际上是range
types的对象。 在这种情况下Set
被省略,因为For Each ... In ... Next
循环为你做。
现在你的实际问题。
-
你会发现
Worksheet.UsedRange
用于确定列数。 这表示从A1到最后一个使用的单元格(这实际上是最后使用的列和最后一个使用的行的交叉点)的工作表中的区域。 鉴于你的数据跨越列A,当它结束时,没有更多的数据不属于任何列的权利,你可以使用ActiveSheet.UsedRange.Columns.Count
来获得你UsedRange
的列数,希望在你的片。 -
我首先提到了
UsedRange
,因为我想让你熟悉它。 我们将用它来解决vlookup
问题。 所以在vlookup
之前我build议的第一步是find带有你的ID的单元。 我们应该先dim
我们将要使用的variables,例如rng3
:
昏暗rng3作为范围
然后我的build议是find单元格ID循环通过A列中的单元格,开始A3,但不循环直到列的末尾,因为有1m行,但直到我们到达最后一个实际使用的行:
For Each cell In wb1.ActiveSheet.Range("A3:A" & wb1.ActiveSheet.UsedRange.Rows.Count) If cell <> "" Then Set rng3 = cell Exit For 'we found the value, no need to continue looping, so we exit the For loop End If Next 'there is no need to write "cell" after "Next", because VBA knows which loop it is in.
现在,我们有你的身份证的单元格,我们可以在以下位置查找:
i = 2 'Starting vlookup Index number per cell in range For Each cell in rng2 cell.Value = "=VLOOKUP(" & rng3.Address & "," & wb2 & "," & i & ",FALSE)" 'again, wb2 is not a nice name for String variable i = i + 1 Next
我希望这里没有错别字,因为我没有testing过。 但是,我已经仔细检查了代码,它看起来不错。
我得到它与工作:
Sub DAc_lookup_headers() Dim wb1 As Workbook 'Current text/file Dim map As String 'reference Map Dim cID As String 'wb1 look up column A Dim rID As String 'wb1 starting row number Dim rng1 As Range 'wb1 Collection header range Dim i As Long 'Index number per cell in range Set wb1 = ActiveWorkbook Set rng1 = wb1.ActiveSheet.[A1:G1] map = ("'C:\Users\x165422\Desktop\New folder\[Reference.xlsx]Ref'!$A$1:$I$13") rID = 2 'Row where ID is - will increment + 1 if not found cID = "A" 'Column where ID is i = 3 'Starting vlookup Index number - to increment per cell in range '>Look for ID until value is found Do rID = rID + 1 wb1.ActiveSheet.[a1].Value = ("=VLOOKUP(" & cID & rID & "," & map & "," & i & ",FALSE)") Loop Until wb1.ActiveSheet.[a1].Text <> "#N/A" Or "0" '> Populate remining headers For Each cell In rng1 cell.Value = ("=VLOOKUP(" & cID & rID & "," & map & "," & i & ",FALSE)") i = i + 1 Next '> Convert to values With rng1 .Value = .Value End With End Sub