0

ワークシート A、B、C があります。ワークシート A には日付の列が含まれています。B と C にはそれぞれ 2 つの列が含まれています。1 つは日付、もう 1 つは値です。例えば

ワークシート A:

     A           B
1    2001-01-01  ---
2    2001-01-02  ---

ワークシート B:

     A           B
1    2001-01-01  1

ワークシート C:

     A           B
1    2001-01-02  2

=Search(W, date)ワークシートから実行すると、ワークシートAに割り当てられた値を返す関数が必要です。たとえば。dateWSearch(C, "2001-01-02")=2

これは、指定された日付での通貨レートの検索の抽象的なバージョンです。複数のワークシートに通貨のレートが含まれているため、検索すると、どのワークシート (通貨) を選択するかがわかります。

そのような関数を定義する方法は? パラメータをカスタム マクロに渡そうとしましたが、Excel で不可解なエラーが発生し続けます。選択したセルをソースとするマクロも使いやすそうですが、関数の方がいいですね。

編集:私の試みはうまくいきません

Function FindRate()
    Dim FindString As String
    Dim Rate As String
    Dim Src As Range
    Dim Found As Boolean

    MsgBox sheet_name
    Rate = "Not found "
    Set Src = Application.ActiveCell
    FindString = "2006-12-19"
    Sheets("cur CHF").Activate
    Found = False
    For Each c In [A1:C2000]
        If c.Value = FindString Then
            Rate = c.Offset(0, 1).Value
            Found = True
            Exit For
        End If
        Next

    MsgBox Rate
    'FindRate = Rate
End Function



Function Rate(cname As String)
    Dim sheet_name As String
    Dim c2s As New Collection

    c2s.Add "cur worksheet name", "cur"

    sheet_name = c2s.Item(cname)
    Call FindRate(sheet_name)

End Function
4

2 に答える 2

0

あなたが実際に行っているのはルックアップです。VLOOKUPあなたが望むことを正確に行うExcelに組み込まれた関数があります。構文は

VLOOKUP(lookup_value, table_array, col_index_num, [range_lookup])

lookup_valueこれにより、テーブルの値が検索されますtable_arrayrange_lookupfalseの場合、最初の列で完全一致が検出されます。それ以外の場合は、最も近い値が検出されます(より高速ですが、データを並べ替える必要があります)。

列の値を返しcol_index_numます。

あなたの場合、「2012-01-01」に対応するシートBの値が必要な場合は、

=VLOOKUP("2012-01-01", Sheet2!A2:B1000, 2, false)

日付文字列を日付値に変換するなどの手間がかかる場合があります。値をSheet2日付として追加した場合は、次を使用します。

=VLOOKUP(DATEVALUE("2012-01-01"), Sheet2!A2:B1000, 2, false)

その関数は文字列 "2012-01-01"をExcelが。として認識するものに正しく変換するためDATEです。

ここで、アクセスする必要のあるシートが事前にわからない場合(これは変数であるため)、VBA関数を自分で作成する必要がある場合があります。

Function myLookup(value, curr)
Dim dval As Long, luTable As Range, s As Worksheet, c As Range

' if user types date as string, convert it to date first...
If VarType(value) = vbString Then
  dval = DateValue(value)  ' this doesn't work if dval hasn't been declared as `long`!
Else
  dval = value
End If

' see if `curr` is the name of a defined range; if so, use it
On Error GoTo notArange
' if the next line doesn't generate an error, then the named range exists:
Set luTable = Range(curr)
' so let's use it...
GoTo evaluateFunction

notArange:
' If we got here, "curr" wasn't the name of a range... it must be the name of a sheet
' first, tell VBA that we're done handling the last error:
Resume here
here:
On Error GoTo noSheet
Set s = ActiveWorkbook.Sheets(curr)

Dim firstCell As Range, lastCell As Range
Set firstCell = s.Range("a1")
Set lastCell = s.Range("b1").End(xlDown) ' assuming data in columns A and B, and contiguous
Set luTable = Range(firstCell, lastCell)

evaluateFunction:
myLookup = Application.WorksheetFunction.VLookup(dval, luTable, 2, False)
Exit Function

noSheet:
' get here if currency not found as either sheet or range --> return an error message
myLookup = curr & " not found!"

End Function

これは小さなサンプルでテストされ、機能しました。注意すべきいくつかのこと:

それぞれを別々のシートに保持する代わりに、変換が保持される範囲( "euro"、 "dinar"、 "yen"、...)に名前を付けることができます。次に、範囲の名前(便宜上、通貨の名前と同じにします)をパラメーターとして関数に渡し、。を使用してアクセスできますRange(currency)。これは、範囲のサイズの「ハードワイヤリング」の問題も回避します

この関数は、名前付き範囲の存在を確認し、存在する場合はそれを使用します。そうでない場合は、正しい名前のシートを探します

「無効な通貨名」を使用すると、これが戻り値に反映されます(したがってmyLookup("01-01-2012", "Florins")"Florins not found!"

特定の長さのルックアップテーブルを想定する代わりに、End(xlDown)構成を使用してテーブルのサイズを動的に決定します

String日付を、またはとして渡すことを許可しますDATEVALUE。関数は文字列に気づき、それを変換します

現在、range_lookupパラメータをに設定していますFalse。これは、完全に一致する必要があり、存在しない値はエラーを生成することを意味します。「最適な一致」を返す場合は、パラメータをに設定しますTrue。要求された日付が制限を超えた場合、ごみを返却するリスクがあります。これを解決するには、為替レート列の最初と最後の値を「有効なデータなし」に設定します。ルックアップ関数が戻ると、この値が表示されます。

于 2013-02-13T03:39:51.353 に答える