根据两个参数导出 Excel Table 的单元格值

Derive cell value of an Excel Table based on two parameters

我在 excel 中有 2 列,A 和 B。在 A 中我有百分比(比率),在 B 中有整数(年)。

 rating PD  year
    0.39%   3
    0.88%   2
    1.32%   17
    0.88%   1
    0.26%   15
    0.17%   2
    0.17%   2
    0.59%   2
    0.59%   2

然后我有一个 Table,其中 F 列中有年份,行中有文字。

像这样(table 更大,年数达到 30):

    Rating          
Year AAA     AA+      AA      AA-
1   0.003%  0.008%  0.018%  0.049%
2   0.016%  0.037%  0.074%  0.140%
3   0.041%  0.091%  0.172%  0.277%
4   0.085%  0.176%  0.318%  0.465%
5   0.150%  0.296%  0.514%  0.708%

等等(table 比这个大很多)。

所以我需要一个函数或快捷方式,对于 A 列中的给定比率和 B 列中的给定年份,它会在 C 列中为我提供相应的评级(AAA、AA+、AA 等.).

在 table 中,速率是最高的。因此,如果我有 A1=0.50%B1=2,那么我会去查看第 2 年 table 和相应的比率,即 0.74%(因此是 AA),因为 AA+是 0.37% 并且太低了。

也就是说AA+和year 2都是0.16%到0.37%之间的利率。第 2 年的 AA 利率都在 0.37% 到 0.74% 之间。

你知道我如何完成这个任务吗?

非常感谢。

为了代码的可读性,我使用了两个定制的 functions,以及此处显示的主要过程。否则将是一个巨大的代码转储。

开始之前,您必须change/check这些数据字段

  • (蓝色)数据table需要命名为“scores”(或将内码改成你自己的名字)
  • 同样适用于(绿色)等级 table - 命名为“grades”并从 F1
  • 开始
  • 最后但同样重要的是,代码假定这两个 table 位于名为“Sheet1
  • 的 sheet 中

So all of this needs to be changed within the code, if the names do not match!

现在进入程序:

Option Explicit
Private Sub run_through_scores()

    Dim scores As ListObject ' table from A1
    Dim grades As ListObject ' table from F1
    Set scores = Sheets("Sheet1").ListObjects("scores")
    Set grades = Sheets("Sheet1").ListObjects("grades")

    Dim cell As Range ' for "for" loop
    Dim inrow As Long ' will store in which row the year is
    Dim resultColumn As Integer ' will store in which column the percentage is

    'for every cell in second column of scores table (except header)
    For Each cell In scores.ListColumns(2).DataBodyRange
        inrow = get_year(cell).Row - 1
        ' ^ returns Row where result was found, -1 to accoutn for header

        'using our get_interval() function, _
         determines in which column is the sought percentage
        resultColumn = get_interval(cell.Offset(0, -1), inrow).Column
        cell.Offset(0, 1) = Sheets("Sheet1").Cells(1, resultColumn) 
        'write result in Column C   ^
    Next cell

End Sub

以及函数:

get_year()

returns a Range Object from the "grades" table, in which we found the matching year from our "scores" table. If the desired year is not found, it returns the year closest to it (the last table row)

' Returns a Range (coordinates) for where to search in second table
Private Function get_year(ByVal year As Variant) As Range

    Dim grades As ListObject ' table from F1
    Set grades = Sheets("Sheet1").ListObjects("grades")

    Dim testcell As Range
    Set testcell = grades.ListColumns(1).DataBodyRange.Find(year, LookIn:=xlValues)

    'if found
    If Not testcell Is Nothing Then
        Set get_year = testcell
    Else
        Dim tbl_last_row As Long 'if year not found, return last row
        tbl_last_row = grades.ListColumns(1).DataBodyRange.Rows.Count
        Set get_year = grades.ListColumns(1).Range(tbl_last_row)
    End If

End Function

第二个函数:

get_interval()

returns a Range Object from the "grades" table. It compares individual cell ranges and returns upon a) if the sought percent from "scores" is less or equal (<=) then current cell percent or b) if we went through all the cells, it returns the last cell (because it must be higher, than the maximum of specified interval)

Private Function get_interval(ByVal what As Variant, ByVal inyear As Long) As Range

    Dim grades As ListObject ' table from F1
    Set grades = Sheets("Sheet1").ListObjects("grades")

    Dim cell As Range
    For Each cell In grades.ListRows(inyear).Range

    'check for interval 
        If what <= cell And cell.Column <> 6 Then 'we don't want to check year column
            Set get_interval = cell
            Exit Function
        End If
    Next cell

    ' if we arrived here, at this stage the result will always be the last cell
    Set get_interval = grades.ListRows(inyear).Range(, grades.ListColumns.Count)

End Function

触发(调用)run_through_scores() 过程后,我们得到了预期的结果:


如有任何问题,请告诉我 :)