索引与条件匹配(Excel或VBA)

我在Excel电子表格中有两列:

A | B ---|--- DL | KO D4 | KO SO | PL SS | PL 

这只是一个例子,在我的实际电子表格中,我使用了更长的string。 现在我想实现一些东西,这样下一次我在列A中键入一个以S开头的string时,它会自动填充B的PL,或者如果我键入一个以D开头的string,KO就会出现在B中。如果我键入一个string,比方说,以前没有发生的AL,一个默认的string(比如“FILL IN”或只是空string)被放置在B中。

这个想法是,我将不得不手动键入在B中的string。如果将来我键入一个string匹配AL(不是以A开头,但完全匹配),它将足够聪明,以识别填写什么为B.

第一种方法:Excel

使用索引匹配:

 =INDEX($N:$N;MATCH(ReturnFormattedCredit($K4)&"*";$K:$K;0)) 

它应该返回列N中的string,通过匹配K4中的元素作为列K中其他元素的子string。

帮助函数ReturnFormattedCredit是我自己创build的一个VBA函数:

 Function ReturnFormattedCredit(c) As String 'Returns the formatted credit: For ZK credits this will be the first 3 alphabetical 'characters + the 4 following digits; for ZL credits this will be the first 2 'alphabetical characters + the following 6 digits; return the full string otherwise If StrComp(Left(c, 2), "ZL") = 0 Then ReturnFormattedCredit = Left(c, 8) ElseIf StrComp(Left(c, 2), "ZK") = 0 Then ReturnFormattedCredit = Left(c, 7) Else ReturnFormattedCredit = c End If End Function 

我已经testing了这个函数,它做了它应该做的:从一个可能更大的string中只提取必要的子string。 现在的问题是,它只会查找与K中匹配的顶层元素,然后从该行中的N列返回相应的string。 但是,如果第一个元素不知道string(这意味着:它也使用这个公式,而手动input的地面真相是列中的其他地方),它会引起一个圆的引用,因为现在这个单元格会试图find回答,但会不断尝试评估自己。

可以检查单元格是否是公式不使用.HasFormula,但从上面的例子中,我似乎无法提取INDEX的第二个参数这种方式返回哪个特定的单元格。

第二种方法:VBA

所以我经验不足,不知道如何在Excel中做到这一点:在VBA中试用。

 Function GetProjectName(targetarray As Range, kredietarray As Range, krediet) As String For Each el In kredietarray.Cells targetEl = targetarray(el.Row - 1) If StrComp(ReturnFormattedCredit(krediet) & "*", el) And Not targetEl.HasFormula Then GetProjectName = "test" ' GetProjectName = targetEl End If Next GetProjectName = "No project name found" End Function 

我通过列从中提取string,要search的列和单元格将string分别进行比较:

 =GetProjectName($N2:$N10;$K2:$K10;$K5) 

这应该成为:

 =GetProjectName($N:$N;$K:$K;$K5) 

对于K列中的每个单元格,我都会尝试将K5与该单元格相匹配。 如果匹配,则第二次检查:同一行但N列的单元格不能是Excel公式。 如果这是真的,那么我已经find了我想要的string,该string必须返回。 如果这是一个Excel公式,然后继续寻找。

不幸的是,这没有find任何东西(打印无效的值),或只是打印0.在此函数发送垃圾邮件的Debug.Print消息之前,我得知,该函数往往不能正确执行,我不明白为什么。

如果您重新提出这个问题,可能的解决scheme就会变得更加明显。 所以你可以说这个任务是:

  1. 在列“A”中捕获单元格的更改。 使用单元格值作为数据库查找的关键字,如果该项目存在,则使用该项目填充列“B”中的单元格。
  2. 在列“B”中捕获单元格的更改。 检查列“A”中的单元格是否包含数据库中尚不存在的键,如果不存在,则添加项目和键。

这可以使用Collection作为数据库和Worksheet_Change事件来完成。 因此,在Sheet1的后面代码(或者适用的表单)中,您可以粘贴以下内容:

 Option Explicit Private Const ENTRY_COL As Long = 1 Private Const ENTRY_ROW As Long = 1 Private Const OUTPUT_COL As Long = 2 Private Const OUTPUT_ROW As Long = 1 Private mInitialised As Boolean Private mOutputList As Collection Private Sub Worksheet_Change(ByVal Target As Range) Dim cell As Range Dim entryKey As String Dim v As Variant If Not mInitialised Then Initialise For Each cell In Target.Cells 'Handle if change is in col "A" If Not Intersect(cell, Me.Columns(ENTRY_COL)) Is Nothing Then If Len(cell.Value2) > 0 Then 'Look up item with key entryKey = Left$(cell.Value2, 1) v = Empty On Error Resume Next v = mOutputList(entryKey) On Error GoTo 0 Application.EnableEvents = False 'If item is found, fill col "B" If Not IsEmpty(v) Then Me.Cells(cell.Row, OUTPUT_COL).Value = v Else Me.Cells(cell.Row, OUTPUT_COL).Value = "FILL IN" End If Application.EnableEvents = True End If 'Handle if change is in col "B" ElseIf Not Intersect(cell, Me.Columns(OUTPUT_COL)) Is Nothing Then If Len(Me.Cells(cell.Row, ENTRY_COL).Value2) > 0 Then 'Look up item with key entryKey = Left$(Me.Cells(cell.Row, ENTRY_COL).Value2, 1) v = Empty On Error Resume Next v = mOutputList(entryKey) On Error GoTo 0 'If nothing found then add new item to list If IsEmpty(v) Then mOutputList.Add cell.Value2, entryKey End If End If Next End Sub Private Sub Initialise() Dim r As Long Dim rng As Range Dim v As Variant Dim entryKey As String Dim outputStr As String 'Define the range of populated cells in columns "A" & "B" Set rng = Me.Range(Me.Cells(ENTRY_ROW, ENTRY_COL), _ Me.Cells(Me.Rows.Count, OUTPUT_COL).End(xlUp)) 'Read the values into an array v = rng.Value2 Set mOutputList = New Collection 'Populate the collection with item from col "B" and key from col "A" For r = 1 To UBound(v, 1) If Not IsEmpty(v(r, 1)) And Not IsEmpty(v(r, 2)) Then entryKey = Left$(v(r, 1), 1) outputStr = CStr(v(r, 2)) On Error Resume Next mOutputList.Add outputStr, entryKey On Error GoTo 0 End If Next mInitialised = True End Sub