2011-12-14 10 views
1

範囲の特定の値を検索し、隣接する特性を返す関数を作成しました。VBA:#VALUEでセルをフォーマットするエラー

Function Busca(valor As String) 
    Dim bus(0 To 1) 
    bus(0) = Worksheets("Sheet2").Range("A1:A10").Find(valor, LookAt:=xlWhole). _ 
     Offset(0, 1) 
    bus(1) = Worksheets("Sheet2").Range("A1:A10").Find(valor, LookAt:=xlWhole). _ 
     Offset(0, 2) 
    Busca = bus 
End Function 

A1:A10valorための一致がない場合、関数は{#VALUE,#VALUE}を返し、ウィッヒはOKですが、私は与えられた色で「いいえマッチ」セルで、代わりに{"No match", ""}のようなものを返すようにしたいと思います。私は、データの検証、エラー処理を試してみました。IfThenActiveCell.Interior.ColorIndexは利用できません。また、エラーが修正された場合は、セルを透明に戻したいと思います。

私はイベントハンドラがこのトリックを行うことができたと思いますが、私はVBAで新しく、理解していないことがたくさんあります。

EDIT示唆したように

、明確にする:私は、出力セル(複数可)一致が見つからない場合は、色を変更するには、マッチがある場合は色を持たないためにを作るにはどうすればよい

見つかりました(VBA)?

+1

表示されている関数は何も返しません... VLOOKUP()のようなワークシート式を使用しているだけで構いませんか?関数(ワークシートから呼び出されたとき)は、シートを変更することはできません。呼び出し元のセルにのみ値を返すことができます。色を追加する必要がある場合は、条件付き書式設定を使用できます。 –

+0

私は数式を訂正しました。私は機能がシートを変更できないことを知らなかった。条件付き書式設定として、Subとして機能を追加する方が便利かどうかはわかりません。私は普通のユーザーが物事を変えることができないようにしたいが、仕事場をpwで保護したくない。 – Pragabhava

答えて

3

これは、質問者からの新しい情報の光の中で完全に書き直さ答えです。

私が正しく理解している場合は、セルの色を変更するカスタム関数を作成したいと考えています。カスタム関数のMicrosoftのヘルプから次のテキストは、あなたができないと言う:

カスタム関数で使用することができますVBAのキーワードの数は、あなたがマクロで使用できる数よりも 小さいです。カスタム機能では、 ワークシートの式に値を返すほか、別のVBAマクロまたは関数で使用される式以外の操作を行うことはできません。 たとえば、カスタム関数では、ウィンドウのサイズを変更したり、 セル内の数式を編集したり、 セル内のテキストのフォント、カラー、またはパターンオプションを変更することはできません。この種の「アクション」コードを関数 プロシージャに含めると、関数は#VALUE!を返します。エラー。

私はあなたの要件を満たす可能性のある2つの代替案を知っています。 3番目の選択肢は、後にインスピレーションのフラッシュの後に追加されました。

代替1:許容値

位置制限値を有することであるセルにカーソルのドロップダウンリストを提供します。ツールバーの[データ]を選択し、[検証]を選択します。データ検証フォームが表示されます。

まだ選択されていない場合は、[設定]タブを選択します。 [許可:]の下のボックスをクリックし、[リスト]を選択します。 [ソース]ボックスに「= $ A $ 1:$ A $ 10」と入力します。 ( "="が必要です。このセルのコピーを作成するには、$ sが重要です)。[OK]をクリックします。

ユーザーがカーソルをそのセルに置くと、許可された値を入力するか、リストから許可された値を選択できます。他の値を入力しようとすると、エラーメッセージが表示されます。データ検証フォーム内の他のタブでは、ヘルプメッセージと独自のエラーメッセージを入力できます。

元のボックスに$ sがあるため、元のセルとその検証を他のセルにコピーできます。

オルタナティブ2:条件付き書式

許可された値が範囲であれば、条件付き書式は、要件を満たしています。たとえば、許可される範囲が10〜20であるとします。

ツールバーの[書式]を選択し、条件付き書式を選択します。

条件1のボックスが表示されます。 「間」は既に表示されています。右側のボックスには10と20を入力します。

[条件2のボックスを表示するには、[追加]をクリックします。[より小さい]で置換]を選択し、次のボックスに10と入力します。 OK。

[条件3の置換え]を表示するには、[追加]をクリックします。次のボックスに20と入力します。[書式]をクリックします。色をクリックします。赤を選択します。 [OK]をクリックします。

[OK]をクリックして条件付き書式設定を受け入れます。

ユーザーは、細胞内に好きなものを入力することができますが、それはあなたが望むようにあなたがフォーマットされたセルのように多くのコピーを作成することができます

10〜20である場合を除き、それが赤になります。

ワークシートの変更イベント

私が前のイベントを考えているはずです。私はこれがまさにあなたが望むものだと信じています。

VBAエディタ内では、通常、プロジェクトエクスプローラは画面の左側に表示されます。表示されていない場合は、Ctrl+Rをクリックします。

選択した値を制御するワークシートの行を右クリックします。 View Codeをクリックします。

コード領域はワークシートになりますが、それ以外の場合は空白になります。この領域にはさまざまなルーチンを配置できますが、関連するルーチンはワークシート・イベント・ルーチンです。これらは、ワークシートのアクティブ化または非アクティブ化などのイベントが発生するたびに呼び出されるルーチンです。必要なイベントは、ユーザーがセルを変更するたびに呼び出されるChangeです。このルーチンの魅力は、あなたが望むものを何でもすることができるということです。

ワークシートのコード領域に、以下のWorksheet_Changeルーチンをコピーして貼り付けます。

このパラメータは、ユーザが変更したセルのアドレスです。

TgtRngListには、パトロールする範囲のリストが設定されています。これをC1:C1000、F1:F1000、A1に設定しました。これを巡回する範囲に変更する必要があります。

OKValueListは、パトロールされた範囲の許容値のリストに設定されます。彼らはどこかのシートの中にあるかもしれませんが、私はここでそれらを定義する方が簡単だと思います。あなたが望むものにリストを変更してください。

変更されたセルがパトロールされた領域の1つにあるかどうかをチェックします。そうであれば、許可された値があるかどうかチェックされます。そのチェックの結果、セルが黒または赤に設定されます。

Option Explicit 
Sub Worksheet_Change(ByVal ChangedCell As Range) 

    ' This routine is called whenever the user changes a cell. 
    ' It is not called if a cell is changed by Calculate 

    Dim ColChanged As Integer 
    Dim InxOV As Integer 
    Dim InxTR As Integer 
    Dim OKValueList() As Variant 
    Dim Patrolled As Boolean 
    Dim RowChanged As Integer 
    Dim TgtColLeft As Integer 
    Dim TgtColRight As Integer 
    Dim TgtRngPartList() As String 
    Dim TgtRngList() As Variant 
    Dim TgtRngPart As String 
    Dim TgtRowBottom As Integer 
    Dim TgtRowTop As Integer 
    Dim ValueChanged As String 
    Dim ValueOK As Boolean 

    ' Fill TgtRngList withe ranges that are to be patrolled by this routine 
    TgtRngList = Array("C1:C1000", "F1:F1000", "A1") 

    ' Fill OKValueList with the permitted values for these cells. 
    OKValueList = Array("V1", "V2", "V3", "V4", "V5", _ 
         "V6", "V7", "V8", "V9", "V10") 

    ColChanged = ChangedCell.Column 
    RowChanged = ChangedCell.Row 

    Patrolled = False 
    For InxTR = LBound(TgtRngList) To UBound(TgtRngList) 
    TgtRngPartList = Split(TgtRngList(InxTR), ":") 
    ' Decode top left of range 
    TgtRngPart = TgtRngPartList(LBound(TgtRngPartList)) 
    TgtRowTop = Range(TgtRngPart).Row 
    TgtColLeft = Range(TgtRngPart).Column 
    If LBound(TgtRngPartList) = UBound(TgtRngPartList) Then 
     ' There is no colon so single cell range 
     TgtRowBottom = TgtRowTop 
     TgtColRight = TgtColLeft 
    Else 
     TgtRngPart = TgtRngPartList(UBound(TgtRngPartList)) 
     TgtRowBottom = Range(TgtRngPart).Row 
     TgtColRight = Range(TgtRngPart).Column 
    End If 
    If RowChanged >= TgtRowTop And RowChanged <= TgtRowBottom And _ 
     ColChanged >= TgtColLeft And ColChanged <= TgtColRight Then 
     ' This is a patrolled cell 
     Patrolled = True 
     Exit For 
    End If 
    Next 
    If Patrolled Then 
    With ActiveSheet 
     ValueChanged = .Cells(RowChanged, ColChanged).Value 
     ' Check value against permitted list 
     ValueOK = False 
     For InxOV = LBound(OKValueList) To UBound(OKValueList) 
     If ValueChanged = OKValueList(InxOV) Then 
      ValueOK = True 
      Exit For 
     End If 
     Next 
     If ValueOK Then 
     ' Set cell black 
     .Cells(RowChanged, ColChanged).Font.Color = RGB(0, 0, 0) 
     Else 
     ' Set cell red 
     .Cells(RowChanged, ColChanged).Font.Color = RGB(255, 0, 0) 
     End If 
    End With 
    End If 

End Sub 

これが役に立ちます。

+0

実際、私はコード内にカッコがありませんでした。上記のコメントを参照してください。目的は、入力(この場合はvalor)を範囲と比較することです。たとえば、A1:A10と言います。 'A3'で一致するものが見つかると、関数は' B3:C3'の値を返します。一致するものが見つからない場合は、出力セルの色を変更します。これは本当の問題です。色の部分が変わり、部分が見つからず(ひどくコード化されている)申し訳ありませんが、 'If''' Then'部分は含まれていません。 – Pragabhava

+0

機能に関する情報はとても役に立ちました。ドロップダウンは良い解決策ではありませんが、条件付き書式設定の可能性があります。 '#VALUE'が返された場合、10,000,000のような値を持つようにエラー処理を行い、あなたが言うように条件付き書式を使用することができます。私はまだあなたの答えに記載されているように、私の関数によってトリガされたマクロを作成することを意味するVBAソリューションを好むだろう。 – Pragabhava

+0

私はインスピレーションを受けました。私の答えで第三の選択肢を見てください。 –

0

xlWholeに追加されたオフセットはどこにあるのかわかりません。これはセル全体をチェックするかどうかを示します。ここではいくつかの注意事項があり、あなたはそれが返しますオブジェクトを見つける表示されます。

Function Busca(valor As String) 
''http://msdn.microsoft.com/en-us/library/aa195730(v=office.11).aspx 
Dim bus(0 To 1) 
With Worksheets("Sheet2").Range("A1:A10") 
    Set c = .Find(valor, LookAt:=xlWhole) 
    If Not c Is Nothing Then 
     bus(0) = c.Address 

     Set c = .FindNext(c) 
     If Not c Is Nothing Then 
      bus(1) = c.Address 
     Else 
      bus(1) = "None" 
     End If 
    Else 
     bus(0) = "None" 
    End If 
End With 
Debug.Print bus(0), bus(1) 
Busca = bus 
End Function 
+0

ああ、これは恥ずかしいです。コードに括弧がありません。範囲( "A1:A10")。Find(valor、LookAt:= xlWhole).Offset(0、1) '。私は今それを修正しました。ポイントは、一致したセルの情報と2つのセルの情報を取得することです。 – Pragabhava

+0

@Manuel "一致するものが見つからなければ、出力セルの色が変わります"と言う。出力セルとは何ですか?私はあなたがまだ明らかではないことを恐れています。右のセルが一致すれば、何かを見つけることを意味しますか?そうでない場合は、セルの色を右に変更しますか? – Fionnuala

+0

明快さに欠けて申し訳ありません。出力セルは、関数が入力されたセルになります。私が@ TonyDallimoreの答えに書いたコメントのように、 'F10:F11'セルに関数を入力したとすると、一致するものが見つからなければ' F10'は色を変更します。 – Pragabhava

関連する問題