VBAで式を設定して、値代入するのが簡単かと。
vba
1Sub Test()
2 With Worksheets(1).Range("h2:h" & Worksheets(1).Range("A2").End(xlDown).Row)
3 .Formula2 = "=INDEX(C2:G2,MATCH(MIN(ABS(C2:G2-B2)),ABS(C2:G2-B2),0))"
4 .Value = .Value
5 End With
6End Sub
20万のサンプルデータを作成して計測してみましたが、2秒弱で終わりました。
追記
Excel365で試したのでうまくいきましたが、スピル機能のないバージョンだとうまくいかないかも。
その場合は、配列数式を手作業で入力してから、値貼り付けで値化するといいでしょう。
VBAでセル範囲のデータを配列に格納してループで走査する方法でやってみました。
vba
1Sub test2()
2 Dim tbl() As Variant
3 tbl = Worksheets(1).Range("B2:G" & Worksheets(1).Range("A2").End(xlDown).Row).Value
4 Dim res() As Variant: ReDim res(1 To UBound(tbl), 1 To 1)
5 Dim r As Long, c As Long
6 For r = 1 To UBound(tbl)
7 Dim minDiff As Date, nearTime As Date
8 nearTime = tbl(r, 2)
9 minDiff = Abs(nearTime - tbl(r, 1))
10 For c = 3 To 6
11 Dim diff As Date: diff = Abs(tbl(r, c) - tbl(r, 1))
12 If minDiff > diff Then
13 minDiff = diff
14 nearTime = tbl(r, c)
15 End If
16 Next
17 res(r, 1) = nearTime
18 Next
19 Worksheets(1).Range("H2").Resize(UBound(res)).Value = res
20End Sub
こちらも2秒弱でした。
追記
あれから少し気になったので、配列数式をコピーできないか試してみました。下記でできるようです。
ただし、365での確認ですので、古いバージョンのエクセルで実際にできるかは分かりません。
vba
1Sub Test()
2 Dim lastRow As Long
3 With Worksheets(1)
4 lastRow = .Range("A2").End(xlDown).Row
5 .Range("h2").FormulaArray = "=INDEX(C2:G2,MATCH(MIN(ABS(C2:G2-B2)),ABS(C2:G2-B2),0))"
6 .Range("h2").Copy Destination:=.Range("h3:h" & lastRow)
7 With .Range("h2:h" & lastRow)
8 .Value = .Value
9 End With
10 End With
11End Sub
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/08 20:35 編集