Excelrecursion – 在序列中查找最后一个

使用Excel 2010和有一个零件清单,其中一些可以改变其零件号码。 如果零件已被更改,则它将位于一个工作表(A列)及其新值(B列)中。 这个变化还有一个date时间戳。

OldValue到NewValue

在我所有的零件号码列表中,我需要

  1. 检查部件是否已被更改
  2. 按照它通过它的每一个变化,直到我find最后一个。

最后一个 ”可能意味着什么

  • 列B( newVal )中的值不在列A( oldval )OR中
  • 如果它指向自己(更正),在这种情况下,最新的date时间戳是决定性因素。

更正列表是通过添加一行将其redirect到以前(正确的)版本来input的。 一个例子:

  • oldVal A更改为newVal B 2016-04-08 11:39:04.765

  • oldVal B更改为newVal C 2016-04-08 12:21:39.801

  • 我们发现B – > C的改变是不正确的
  • oldVal C更改为newVal B 2016-04-08 13:44.07.913

我知道一个vLookup不会这样做。 我认为SUMPRODUCT可能会解决第一部分,但我不确定如何做recursion(或者如果可能的话)的时间部分。

任何想法,想法,解决scheme将不胜感激。

编辑

附加信息 –

所需的输出 期望的输出

我想在NewPartNo列中显示的是该零件编号链中的最后一个值。 如果零件编号从A→B→C→D,我想在列A的PartNoNewPartNo列中看到D.

你有一个1960-1新的25 – 1960年。 问题是25-1960然后有一个新的OBB1960VAL。 recursion错误的vals有多less层?

这就是问题 – 在某些地方,一部分可能(最初)是A列中的任何一个。至于多less层 – 我不知道。 可能5-10,也许? 我不完全知道。

编辑2

@ TMDean的解决scheme大部分工作,除了当我有像下面的数据。

递归

如果从A001开始,则映射到B001。 B001最新(最近的date)映射到C001。 C001的映射(本身)与另一个映射具有相同的date时间戳,所以A001应映射到C001。

在逐步执行的function中,它会find第一个(A001 – > B001),但是当它试图find第二个时(B001 – > C001)则会报错。

在上面,查找的正确结果应该是A001 – > C001。

这里有两个UDF1来检索recursion的newVal和它的关联date。

Option Explicit Function newestVal(lu As Range, rng As Range) Dim val As Variant Static app As New Application 'truncate the rng down to the used range Set rng = Intersect(rng, rng.Parent.UsedRange) val = lu.Value2 With rng If IsError(app.Match(lu.Value2, .Columns(1), 0)) Then val = app.Index(.Columns(2), app.Match(val, .Columns(2), 0), 1) Else Do While Not IsError(app.Match(val, .Columns(1), 0)) val = app.Index(.Columns(2), app.Match(val, .Columns(1), 0), 1) Loop End If End With newestVal = val End Function Function latestValDate(lu As Range, rng As Range) Dim d As Long, val As Variant, dbl As Double Static app As New Application 'truncate the rng down to the used range Set rng = Intersect(rng, rng.Parent.UsedRange) val = lu.Value2 With rng If IsError(app.Match(lu.Value2, .Columns(1), 0)) Then val = app.Index(.Columns(2), app.Match(val, .Columns(2), 0), 1) Else Do While Not IsError(app.Match(val, .Columns(1), 0)) val = app.Index(.Columns(2), app.Match(val, .Columns(1), 0), 1) Loop End If For d = app.Match(val, .Columns(2), 0) To rng.Rows.Count If .Cells(d, 2).Value2 = val Then If .Cells(d, 3).Value2 > dbl Then dbl = .Cells(d, 3).Value2 End If End If Next d End With latestValDate = dbl End Function 

在F2:G2中,

 =newestVal(E2,A:C ) =latestValDate(E2,A:C ) 

recursive_newval


¹ 用户定义function(aka UDF)被放入标准模块代码表中。 点击Alt + F11 ,当VBE打开时,立即使用下拉菜单来插入►模块Alt + IM )。 将function代码粘贴到名为Book1 – Module1(Code)的新模块代码表中。 点击Alt + Q返回到您的工作表。

这是所有的伪代码,但它应该让你离开正确的方向。 给我几个小时,我可以为你做,但你可以尝试找出答案。

  If Selection Offset Column + 1 <> vbNullString then newvalue = Selection Offset Column + 1.value for i = 1 to 100 If newvalue Offset Column + 1 = vbNullString then Display (i)a,b,c Exit For ElseIf newvalue Offset Column + 1 <> vbNullString then newvalue = newvalue Offset Column + 1.value Next i 

受Jeeped解决scheme的启发,我想知道是否可以更通用,写了一个recursion版本的VLOOKUP的UDF实现。

这个函数就像VLOOKUP一样工作,除非它将跟随查找值链,直到它到达表的末尾,如问题中所述。

 Option Explicit Function VLOOKUPR(LookupValue As Variant, _ TableArray As Range, _ ColIndexNum As Long, _ RangeLookup As Boolean) Dim LookupIndex Set TableArray = Intersect(TableArray, TableArray.Parent.UsedRange) VLOOKUPR = CVErr(xlErrNA) Do LookupIndex = Application.Match(LookupValue, TableArray.Columns(1), _ IIf(RangeLookup, 1, 0)) If IsError(LookupIndex) Then Exit Do VLOOKUPR = TableArray(LookupIndex, ColIndexNum) If LookupValue <> TableArray(LookupIndex, 1) Then Exit Do LookupValue = TableArray(LookupIndex, ColIndexNum) Set TableArray = Intersect(TableArray, TableArray.Offset(LookupIndex)) Loop Until TableArray Is Nothing End Function 

因为我希望它是通用的,所以如果它存在于列B中,我没有包含它返回查找值而不是VLOOKUPR #N/A的要求。你可以在你用来调用VLOOKUPR的单元格公式中包含这个逻辑。 =IFERROR(VLOOKUPR($E2,$A$2:$A$100,2,FALSE),VLOOKUP($E2,$B$2:$B$100,1,FALSE))