Excel的VB – 列读入一维数组,执行操作,写回命名的范围?

我有一个包含大约60,000条logging的数据集。 拖欠date字段恰好位于处理货币值的字段之后,有时用户偶然在拖欠date字段中input货币值。 此外,他们有时以stringforms(2011年8月2日)或拖欠天数(135或135天)inputdate。 最常用的input方法是以mm / dd / yy格式(08/02/11)。

不幸的是,这个系统的程序员拒绝花时间为这个领域创buildvalidation,所以在获得数据之后,我必须尽可能多地执行validation。 通常情况下,我会用一些简单的公式来处理这个问题,然而,用户input数据有19种不同的方式,我需要能够快速处理每个数据。 将列加载到数组似乎是最好的select。

我的想法是将列加载到一个数组中,循环遍历它,处理所有的入口选项(或删除那些完全搞砸的),然后把它写回到工作表中。 我知道数据types是下面的数组的第一个问题,但我只在Excel VB中使用过一次数组,我不太确定我做错了什么。 第三行代码是第一个问题。 谢谢你的帮助。

每项BRETTDJ的评论工作代码

'Perform housekeeping on delinquency date Dim delinquency() delinquency = Application.Transpose(Range("AH1:AH" & importwsRowCount)) For i = LBound(delinquency) To UBound(delinquency) If InStr(delinquency(i), ".") Then delinquency(i) = Empty Debug.Print "Emptied an array element at row " & i + 1 End If 'Additional string or numeric operations here to reformat bad entries. Next i Set delRange = Range("AJ1:AJ" & importwsRowCount) iWS.names.Add Name:="dRange", RefersTo:=delRange delinquency = Application.Transpose(delinquency) 'Transpose rows and columns Range("dRange").Value = delinquency 'Write array to worksheet 

不合格进入例子需要重新规划
九月 25,20 (不要年,不要删!)
9月 (无年,无用,删除)
N / A (垃圾!已删除)
LONG TIME AG (白痴认为这是一个好主意,请删除。)
200年6月30日 (显然这个字段只能保存12个字符,删除。)
CHARGED OFF (无用,删除)
94天 (取所有空格前的字符,并从包含订单date的其他字段中减去以获得拖欠date。)
94 DPD (在某些人的DPD中,聪明的头脑代表“过去的日子”,我相信,和上面一样)
(不知道附加的号码是什么,请在空格之前把所有字符转换。)
无效 (删除)
空白 (什么也不做)
12282009 (使用嵌套的左和右和与之间的/ CONCATENATE)
9202011 (添加前导零,然后与上面相同。)
92410 (添加前导零,这将转换为09/24/10)
41261 (自1899年12月31日起,这将转换为12/08/12)
1023 (违约天数,从订单date扣除以得到拖欠date。)
452 (同上)
12 (同上)
1432.84 (货币价值,被低智商的奴隶误入了)删除。

更新的代码,包括删除错误的条目(正在进行中)

 'Perform housekeeping on delinquency date Columns("AH:AH").Select Selection.NumberFormat = "0" Selection.Copy Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _ True, Transpose:=False Dim delinquency() ReDim del(1 To importwsRowCount, 1 To 1) del = Range("AH1:AH" & importwsRowCount).Value For i = LBound(del, 1) To UBound(del, 1) delChars = Len(del(i, 1)) 'Determine length of entry If IsNumeric(del(i, 1)) = True Then 'Determine datatype of entry delType = "Numeric" Else delType = "String" End If If InStr(del(i, 1), ".") Then 'Removes monetary entries like 142.84 del(i, 1) = Empty ElseIf InStr(del(i, 1), "*") Then 'Removes ***INVALID*** entries del(i, 1) = Empty ElseIf delChars = 12 Then 'Removes all entries that extend beyond the 12 character limit of the field and get cut off del(i, 1) = Empty ElseIf delType = "String" And Len(del(i, 1).Value) < 10 And InStrRev(del(i, 1).Value, " ") Then 'Takes the number from entries like 2194 Days or 23 DPD del(i, 1).Value = Left(del(i, 1).Value, Len(del(i, 1).Value) - InStrRev(del(i, 1).Value, " ")) If IsNumeric(del(i, 1)) = False Then 'If the characters to the left of the space are not numbers, discard del(i, 1).Value = Empty Else del(i, 1).Value = Format((CLng(Range("E" & i + 1).Value) - Abs(del(i, 1).Value)), "mm/dd/yy") 'Pull order date and subtract days from it for delinquency date End If ElseIf delType = "Numeric" And Len(del(i, 1)) = 5 Then If del(i, 1).Value > CLng(Date) Then 'Value is greater than todays date, improperly formated date that needs character manipulation and / added del(i, 1).Value = Format(del(i, 1).Value, "000000") 'Add leading zero del(i, 1).Value = DateSerial(Right(del(i, 1).Value, 2), Left(del(i, 1).Value, 2), Right(Left(del(i, 1).Value, 2), 4)) 'Grab year, then month, then day for serialize Else del(i, 1).Value = Format(del(i, 1).Value, "mm/dd/yy") 'Properly formated date that just needs format conversion End If ElseIf delType = "Numeric" And (delChars = 7 Or delChars = 8) Then If delChars = 7 Then del(i, 1).Value = Format(del(i, 1).Value, "00000000") 'Add leading zero End If del(i, 1).Value = DateSerial(Right(del(i, 1).Value, 4), Left(del(i, 1).Value, 2), Right(Left(del(i, 1).Value, 2), 6)) 'Grab year, then month, then day for serialize ElseIf delType = "Numeric" And delChars < 5 Then del(i, 1).Value = Format((CLng(Range("E" & i + 1).Value) - Abs(del(i, 1).Value)), "mm/dd/yy") End If Next i Set dRange = Range("AJ1:AJ" & importwsRowCount) iWS.names.Add Name:="dRange", RefersTo:=delRange delinquency = Application.Transpose(delinquency) 'Transpose rows and columns Range("dRange").Value = delinquency 'Write array to worksheet 

行的原因

 delinquency = Application.Transpose(["AH1:AH" & importwsRowCount]) 

错误是["AH1:AH" & importwsRowCount]无效(它返回一个string,而不是范围)。

[...]Evaluate方法的捷径。 要得到它返回一个范围参考,你需要做一些像[AH1:AH60000]即没有"" 。 常规参考范围会更好

 delinquency = Application.Transpose(Range("AH1:AH" & importwsRowCount])) 

也就是说,如果您将delinquency宣布为二维数组,您实际上不需要使用Transpose

 ReDim delinquency(1 To importwsRowCount, 1 To 1) 

所以,你的代码变成了

 Dim delinquency() As Variant ReDim delinquency(1 To importwsRowCount, 1 To 1) delinquency = Range("AH1:AH" & importwsRowCount).Value For i = LBound(delinquency, 1) To UBound(delinquency, 1) If InStr(delinquency(i, 1), ".") Then delinquency(i, 1) = Empty End If 'MANY ADDITIONAL OPERATIONS HERE Next i Set delRange = Range("AJ1:AJ" & importwsRowCount) iWS.Names.Add Name:="dRange", RefersTo:=delRange Range("dRange").Value = delinquency 'Write array to worksheet 

笔记:

  1. Range("AH1:AH" & importwsRowCount)引用ActiveSheet上的范围
  2. 为了保持健壮,您应该在工作表参考中明确指出。 所以使用类似的东西

 Dim wsData as Worksheet Set wsData = ActiveSheet ' or whatever sheet you want delinquency = wsData.Range("AH1:AH" & importwsRowCount).Value Set delRange = wsData.Range("AJ1:AJ" & importwsRowCount) 'assuming you want to refer to the same sheet iWS.Names.Add Name:="dRange", RefersTo:=delRange ' not sure what this is for, but be sure your Name referes tot he right sheet ' Might be better to use this, if you need to use the Name at all iWS.Names("dRange").RefersToRange = delinquency 

鉴于你接受了克里斯的后一篇文章,这部分内容与我之前的评论部分覆盖了相同的内容,我已经更新了这篇文章,作为这些改变的回答(在我之前的评论中第一个标记)

  1. 在使用它来捕捉范围之前,不需要重新定义变体arrays。 这是一个冗余的行,因为变体arrays自动适合所馈入的范围。
    ReDim delinquency(1 To importwsRowCount, 1 To 1)
  2. 稍微调整,但使用Value2比使用范围时的默认Value要好

然后,您可以select设置定义为行x列列x行的变体数组。

通常情况下,第一种方法是转换只在需要的时候才被采用

  1. 你正在处理一个单独的列或行,你想用一维数组(根据你的问题 – 所以是Transpose仍然是必需的)
  2. 稍后的ReDim将用于调整数组行的大小。 当使用Redim Preserve ,只能调整最后一个尺寸。 所以,如果您以后想要减less与数组中行有关的数据量,则需要使用Transpose设置数组来生成列x行

我关于变体数组的文章位于EE paywall之外。 你可以试着再看一遍吗?

标准用法

 Sub RowByColumn() Dim delinquency() delinquency = Range("AH1:AH" & importwsRowCount).Value2 

转置的使用

 Sub ColumnByRow() 'creates a 1D array when working on a single column or row. creates a *column X row* array on a 2D array Dim delinquency() delinquency = Application.Transpose(Range("AH1:AH" & importwsRowCount).Value2)