2015-06-01 82 views
0

我一直在解决以下问题一段时间,并且我得到了一个非常基本的版本,可以在没有错误处理的情况下工作。我的目标是让这个宏从个人宏观工作簿中运行。从已关闭的工作簿填充正确的标题

我正在从各种来源导入管道分隔的文本文件,并且标题中的格式都不匹配(某些提供程序决定使用整个布局)。有了这个问题,我创建了一个名为Reference(又名Map)的Excel工作簿,其中包含传入文件布局和标准化/更正列的名称格式。

对我来说好消息是,文件ID将始终在A列。我每个月需要处理约65个文件,因此我需要尽量减少所有可能的步骤,因此需要关闭参考工作簿。

因此,我在网上环顾四周,将大部分解决方案放在一起,根据位于A3中的ID拉入新的标题。然而,仍然存在一个困境,有时A3上的ID不会存在于参考工作簿上 - 我需要让vlookup向下移动到下一行,直到结果不等于#N/A或0或空白。

在这一点上,我得到'Do Loop Until'为第一场比赛找到正确的一行 - 完全无法跟随它后面的任何代码。

只要vlookup找到一个包含现有ID的行,然后运行下面的代码片段来填充剩余的标头。下一步的唯一副作用是,由于某种原因,rID偏移+1行,如果最后一行不包含匹配的ID,则撤消'Do Loop'直到'。

'> 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 
+0

旨在为数字您的任何头?我发现.txt文件在分隔后经常会有拖尾/前导空格,而这会将它们转换为字符串。 – TMH8885

+0

所有标题都是文本 - 清理的目的是为了能够减少通过查询运行的Microsoft Access文件的数量来清理数据。我每个月处理几百万个单独的条目。如果所有文件具有相同的头文件,那么导入Access的过程将是一个巨大的缓解。 – ExcelNovice2015

+0

我最终取消了列计数验证,因为我可以编辑vlookup并添加更多字段。 – ExcelNovice2015

回答

1

我会尽力帮助一点,因为你表现出精力来学习。我会给你一些关于整体VBA编码的有用提示,以及关于你的问题。请尽量记住它们。

  1. 由于您的变量名称很差,很难读取您的代码。在VBA中,单元格和它的值之间存在差异。在你的代码中你有rng1rng2。我看到当前rng1代表单元格的值,而rng2 - 单元格本身。我不确定你是否故意这样做,但现在你会理解它。如果你的意思是一个单元本身,那么命名变量rng2是很好理解的。但是,如果你指的是单元格的价值,那么命名变量rng1是有误导性的。这只是为了能够更轻松地阅读代码。由于您将此变量定义为string,我怀疑您希望它获得string类型的值。因此,您应该将变量命名为与其类型相关的内容,即以str...s...开头的内容,这意味着此变量的类型为string,例如, strValuesID。最好的方法是使用str,因为s可能会与single类型混淆(在VBA中也有这样的数据类型)。您应该将此逻辑应用于您使用的每个变量。 String - str...,long - lng...,integer - int...,double - dbl...,boolean - bln...等等。一种类型是特定类型,您也可以在此处使用它。这是object类型。对象不仅仅是对象,它们被分解为许多不同的类型,并且在你的代码中你也使用了对象rangeworkbook。你能说出他们o...obj...,或者它通常最好使用一个更具体的名称,如rng...(为范围)或wb...(为工作簿)。通常的数据类型的变量可取的值而不Set子句,而对象总是需要Set为了与一些实际对象关联,像范围,工作簿时,片材等。在您的代码,我们看到wb2变量这是一个string。现在你知道,那不好。 因此,在这种情况下,你应该,如果你希望它是string而不是range,学会始终使用此命名约定重命名rng1。同样适用于wb2

  2. 在所有sub s之前,始终使用Option Explicit作为代码模块中的最顶层行。这只是防止错别字。这实际上是一条不可或缺的路线。我总是使用它,每个人都应该。这样做后,我看到你的代码不会运行,因为cell变量没有定义。使用Dim cell As Range,因为单元格实际上是range类型的对象。在这种情况下,Set被省略,因为For Each ... In ... Next循环会为您执行该操作。

现在你的实际问题。

  1. 您会发现Worksheet.UsedRange对确定列数有用。这表示从A1到最后一个使用的单元格(这实际上是最后使用的列和最后一个使用的行的交叉点)的工作表中的区域。假设你的数据从A列跨越,当它结束还有没有更多的数据是正确的不属于任何列,您可以使用ActiveSheet.UsedRange.Columns.Count让你UsedRange,希望在您的工作表中的列数。

  2. 我提到UsedRange第一,因为我想让你得到熟悉它。我们将用它来解决vlookup的问题。因此,在vlookup之前我建议的第一步是找到带有您的ID的单元。我们应该首先使用dim个变量,例如rng3

Dim rng3 As Range

那么我的建议是找到ID通过细胞在A列循环,开​​始的A3,但不循环,直到柱末端的小区,因为有1米行,但直到我们达到最后的实际使用排:

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. 

现在,我们有你自己的ID为单元,我们可以把查找在:

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 

我希望这里没有错别字,因为我没有测试过它。但是,我仔细检查了代码,它看起来不错。

+0

感谢ZygD的详细概述,具有良好特定名称的属性使得完全有意义;特别是如果共享代码。 – ExcelNovice2015

0

我得到它一起工作:

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 
相关问题