2012-04-30 3 views
3

私は彼が同様にコラム「絶縁体」で彼はA与えられた選択肢「AlやCu」を検証するかどうか

を与えられているコラム「導体」に例について ..私は彼に選択肢を与えていたために、ユーザからの入力を取っています選択肢「XLPEまたはPVC」

今、上記の二つは、私がユーザーに与えているリストのシンプルなバージョンがありますが、私のリストの一部は、以前の入力に依存し、そのために私はこのようなdatavalidationを使用しています:

=indirect($C5 & "_" & $D5) 

(例:al_xlpeの名前付き範囲)

列CとDがいくつかの入力を参照していると仮定します(これにより、2になります!名前付き範囲は先に定義されている)。

私は私の検証リストの選択肢のいくつかは4オーバー以上の入力に依存して、彼らはこのように行く(名前付き範囲を大量に使用することを余儀なくされている上記の方法のため、次

=indirect("col6" & "_" & col7 & "_" & col8 & "_" & col9) 

(という名前の別例えばのための範囲:al_xlpe_duct_3;これらの4が存在することができる)

私が直面していますいくつかの問題があります!

  1. をデータベースが4以上の入力からなる検証リストにいつでも展開することができますので、が4が必要になります!名前付き範囲が変更されます。
  2. データ検証が容易に(大きな問題)
  3. 私はコピーを制限し、(列は固定されませんので、カントの使用のインポートを)他のシートからのデータを貼り付けることになる私のユーザーのほとんどは貼りカント私はカント
  4. 失われますリストボックスを使用することができます。これは、各行に任意の数の行を入力できるためです。
  5. 私のツールは入力データに対して機能し、ほとんどのユーザーはアクセスに慣れていないため、 (また、データの貼り付けが簡単にできない)

より良い方法は?

答えて

1

プログラマーとして45歳になってから仕事を始めると非常に普及したテクニックを提供します。私たちはコンパイラ開発からこの技術を借りてきましたが、正式にそれを使用しました。

  1. デザイン人間のための便利な方法で仕様を符号化する方法であって、本格的な技術で

    は、5つのステップが存在することになります。

  2. 仕様をエンコードします。
  3. 高速処理に便利な方法で仕様を保持する1つまたは複数のテーブルを設計します。
  4. ヒューマンフォーマットを高速処理フォーマットに変換するプログラムを設計して実装します。
  5. 高速処理形式を解釈し、必要な操作を実行するプログラムを設計して実装します。

すべての問題で5つのステップすべてが必要なわけではありません。時には人間と高速処理の形式が同じになることがあります。これは複雑に聞こえるかもしれませんが、複雑な問題を簡単かつ効率的に解決することができました。

以下のワークシートでは、必要な検証の種類を理解しています。

行2では、C列のセルがV1またはV2またはV3またはV4の値を取ると宣言します。

行3では、同じ行の列Cの値がV1またはV2の場合にのみ、列Dのセルの値がV5であると宣言します。

行4では、列D内のセルの代替値を、それ自身の条件セットで宣言します。

行5では、同じ行の列Dの値がV5で列の列Cの値がV1である場合のみ、列EのセルがV7またはV8の値をとることが宣言されています。

私は、これがあなたの検証要件の最高または完全な表現であるかどうかを知るための要件を十分に理解していません。しかし、このテクニックが好きな人は、あなたがそのアイデアを手に入れて、あなたの必要条件を表現するのに役立つことを願っています。

次は、この仕様の高速処理形式を定義する必要があります。私は4つのテーブルを設計し、この答えに配置することがイミディエイトウィンドウに出力し、これらのテーブルの内容の準備ができて、その後高速処理フォーマットに人間のワークシートのフォーマットを変換し、それ以下のコードを実装している:

Rules per Column table 
C RR RR    = Column First rule Last rule 
3 1 1 
4 2 3 
5 4 7 

あります列3(C)、4(D)および5(E)である妥当性検査規則がワークシートにある3つの列。上記の表は、列3(C)については、規則1から規則1が適用され、列5(E)では規則4から7が適用されることを示している。

Rule table    
I VV VV CC CC = Index First value Last value First condition Last condition 
1 1 4 1 0 
2 5 5 1 1 
3 8 8 2 2 
4 11 12 3 4 
5 15 16 5 6 
6 19 20 7 8 
7 23 24 9 10 

ルール1の場合、条件1〜0が適用されます。条件はありません。許可される値は、値テーブルのエントリ1〜4(V1、V2、V3およびV4)です。これは、ワークシートの2行目に相当します。

ルール4の場合、許可される値は、条件3〜4が適用される値テーブルのエントリ11と12(V7とV8)です。条件3は、列4(D)が値テーブル内の項目13(V5)と等しくなければならないことである。条件4は、列3(C)が値表の項目14(V1)と等しくなければならないことである。これは、ワークシートの行5に対応します。

Condition table 
I C VV VV   = Index Column First value Last value 
1 3 6 7 
2 3 9 10 
3 4 13 13 
4 3 14 14 
5 4 17 17 
6 3 18 18 
7 4 21 21 
8 3 22 22 
9 4 25 25 
10 3 26 26 

Value table     Entries 1 to 26 
E 1=V1 E 2=V2 E 3=V3 E 4=V4 E 5=V5 E 6=V1 E 7=V2 E 8=V6 E 9=V3 E10=V4 
E11=V7 E12=V8 E13=V5 E14=V1 E15=V9 E16=V10 E17=V5 E18=V2 E19=V11 E20=V12 
E21=V6 E22=V3 E23=V13 E24=V14 E25=V6 E26=V4 

リンクテーブルを使用してコードを制御することに慣れていない場合、これは完全に理解するのに少し時間がかかることがあります。私はいくつかのルールのためにリンクをたどってきました。もう少しお試しください。あなたはそのアイデアを得るでしょう。ワークシートは、人間が簡単に扱えるように設計されていますが、これらのテーブルはコンピュータで高速に実行できるように設計されています。

このコンパイルプロセスは、ワークシートオープンルーチン内にあるか、ワークブックにテーブルをあらかじめコンパイルして保存することができます。これらの表は、ワークシート変更ルーチンで実行する準備が整っているか、適切なセルに式を計算して配置するために使用できます。

私はこれを説明して、このテクニックがあなたの問題に適しているかどうかを判断するのに十分だと思います。必要に応じて質問に戻ることができ、説明を広げます。

次のコードは、人間のフォーマットを高速処理フォーマットに変換し、高速処理フォーマットを直接ウィンドウに出力します。

Option Explicit 

    Type typColRule  ' Definition of entry in Rules per Column table 
    InxRule1 As Long ' Index of first rule for this column.) InxRule1 > InxRuleL 
    InxRuleL As Long ' Index of last rule for this column. ) if no rules for column 
    End Type 
    Type typRule   ' Definition of Rule table 
    InxValue1 As Long ' Index of first permitted value for this rule 
    InxValueL As Long ' Index of last permitted value for this rule 
    InxCond1 As Long ' Index of first condition for this column.) InxCond1 > InxCondL 
    InxCondL As Long ' Index of last rule for this column.  ) if no rules for column 
    End Type 
    Type typCond   ' Definition of Condition table 
    Col As Long  ' Column to which this condition applies 
    InxValue1 As Long ' Index of first permitted value for this condition 
    InxValueL As Long ' Index of last permitted value for this condition 
    End Type 

    ' ColRule is sized to (Min to Max) where Min is the lowest column validated 
    ' and Max is the highest column validated. ColRule(N).InxRule1 identifies 
    ' the first rule in Rule for column N. ColRule(N).InsRuleL identifies the 
    ' last rule in Rule for column N. 
    Dim ColRule() As typColRule 

    ' There is one entry in Rule per validation row in worksheet "Validate". 
    Dim Rule() As typRule 

    ' There is one entry in ValueCell per value referenced in a permitted or 
    ' a condition. 
    Dim ValueCell() As String 

    ' There is one entry in Cond per condition in worksheet "Validate" 
    Dim Cond() As typCond 

Sub CompileValidation() 

    Dim ColCodeCrnt As String 
    Dim ColNumCrnt As String 
    Dim ColValCrnt As Long 
    Dim ColValidateCrnt As Long 
    Dim ColValMin As Long 
    Dim ColValMax As Long 
    Dim ConditionCrnt As String 
    Dim InxCondCrnt As Long 
    Dim InxRuleCrnt As Long 
    Dim InxValueCellCrnt As Long 
    Dim InxValueListCrnt As Long 
    Dim NumCond As Long 
    Dim NumValue As Long 
    Dim PermittedCrnt As String 
    Dim PosEqual As Long 
    Dim RowValidateCrnt As Long 
    Dim ValueList() As String 

    With Worksheets("Validate") 

    ' Determine the size of the arrays to which information will be 
    ' compiled. Find 
    ' * The minimum and maximum columns subject to validated 
    ' * Number of conditions 
    ' * Number of values references 
    ' This routine does not allow for blank rows or columns in the 
    ' middle of worksheet "Validate". 
    ColValMin = -1 
    ColValMax = -1 
    NumCond = 0 
    NumValue = 0 
    RowValidateCrnt = 2 
    Do While True 
     PermittedCrnt = .Cells(RowValidateCrnt, 1).Value 
     If PermittedCrnt = "" Then 
     Exit Do 
     End If 
     PosEqual = InStr(1, PermittedCrnt, "=") 
     Debug.Assert PosEqual > 1 
     ' Determine range of columns validated 
     ColCodeCrnt = Mid(PermittedCrnt, 1, PosEqual - 1) 
     ColNumCrnt = Range(ColCodeCrnt & "1").Column 
     If ColValMin = -1 Then 
     ColValMin = ColNumCrnt 
     ElseIf ColValMin > ColNumCrnt Then 
     ColValMin = ColNumCrnt 
     End If 
     If ColValMax = -1 Then 
     ColValMax = ColNumCrnt 
     ElseIf ColValMax < ColNumCrnt Then 
     ColValMax = ColNumCrnt 
     End If 
     ' Determine number of conditions and number of values 
     ValueList = Split(Mid(PermittedCrnt, PosEqual + 1), "|") 
     NumValue = NumValue + UBound(ValueList) - LBound(ValueList) + 1 
     ColValidateCrnt = 2 
     Do While True 
     ConditionCrnt = .Cells(RowValidateCrnt, ColValidateCrnt).Value 
     If ConditionCrnt = "" Then 
      Exit Do 
     End If 
     PosEqual = InStr(1, ConditionCrnt, "=") 
     Debug.Assert PosEqual > 1 
     ValueList = Split(Mid(ConditionCrnt, PosEqual + 1), "|") 
     NumValue = NumValue + UBound(ValueList) - LBound(ValueList) + 1 
     ColValidateCrnt = ColValidateCrnt + 1 
     Loop 
     NumCond = NumCond + ColValidateCrnt - 2 
     RowValidateCrnt = RowValidateCrnt + 1 
    Loop 

    ' Size arrays 
    ReDim ColRule(ColValMin To ColValMax) 
    ReDim Rule(1 To RowValidateCrnt - 2) 
    ReDim ValueCell(1 To NumValue) 
    ReDim Cond(1 To NumCond) 

    InxRuleCrnt = 0 
    InxValueCellCrnt = 0 
    InxCondCrnt = 0 

    ' Extract rules in column number order 
    For ColValCrnt = ColValMin To ColValMax 
     ' The first rule for this column, if any, will be the 
     ' next entry in the Rule table 
     ColRule(ColValCrnt).InxRule1 = InxRuleCrnt + 1 
     ' If there are no rules for this column, the last rule index 
     ' will be less than the first rule undex 
     ColRule(ColValCrnt).InxRuleL = InxRuleCrnt 
     RowValidateCrnt = 2 
     Do While True 
     PermittedCrnt = .Cells(RowValidateCrnt, 1).Value 
     If PermittedCrnt = "" Then 
      Exit Do 
     End If 
     PosEqual = InStr(1, PermittedCrnt, "=") 
     ColCodeCrnt = Mid(PermittedCrnt, 1, PosEqual - 1) 
     ColNumCrnt = Range(ColCodeCrnt & "1").Column 
     If ColNumCrnt = ColValCrnt Then 
      ' This rule is for the current column 
      InxRuleCrnt = InxRuleCrnt + 1 
      ' This could be the last rule for this column so 
      ' store its index against the column 
      ColRule(ColValCrnt).InxRuleL = InxRuleCrnt 
      ' The first value for this rule will be the next 
      ' entry in the Value table 
      Rule(InxRuleCrnt).InxValue1 = InxValueCellCrnt + 1 
      ValueList = Split(Mid(PermittedCrnt, PosEqual + 1), "|") 
      ' Save each permitted value in the Value table 
      For InxValueListCrnt = LBound(ValueList) To UBound(ValueList) 
      InxValueCellCrnt = InxValueCellCrnt + 1 
      ValueCell(InxValueCellCrnt) = ValueList(InxValueListCrnt) 
      Next 
      ' Record the index of the last permitted value for this rule 
      Rule(InxRuleCrnt).InxValueL = InxValueCellCrnt 
      ' The first condition for this rule, if any, will be the next 
      ' entry in the Condition table 
      Rule(InxRuleCrnt).InxCond1 = InxCondCrnt + 1 
      ' If there are no conditions for this rule, the last condition 
      ' index will be less than the first condition undex 
      Rule(InxRuleCrnt).InxCondL = InxCondCrnt 
      ColValidateCrnt = 2 
      Do While True 
      ConditionCrnt = .Cells(RowValidateCrnt, ColValidateCrnt).Value 
      If ConditionCrnt = "" Then 
       Exit Do 
      End If 
      InxCondCrnt = InxCondCrnt + 1 
      PosEqual = InStr(1, ConditionCrnt, "=") 
      ColCodeCrnt = Mid(ConditionCrnt, 1, PosEqual - 1) 
      ColNumCrnt = Range(ColCodeCrnt & "1").Column 
      ' Store the column for this condition 
      Cond(InxCondCrnt).Col = ColNumCrnt 
      ' The first value for this condition will be the next 
      ' entry in the Value table 
      Cond(InxCondCrnt).InxValue1 = InxValueCellCrnt + 1 
      ValueList = Split(Mid(ConditionCrnt, PosEqual + 1), "|") 
      For InxValueListCrnt = LBound(ValueList) To UBound(ValueList) 
       InxValueCellCrnt = InxValueCellCrnt + 1 
       ValueCell(InxValueCellCrnt) = ValueList(InxValueListCrnt) 
      Next 
      ' Record last value for this condition 
      Cond(InxCondCrnt).InxValueL = InxValueCellCrnt 
      ColValidateCrnt = ColValidateCrnt + 1 
      Loop 
      ' Record last condition for this rule 
      Rule(InxRuleCrnt).InxCondL = InxCondCrnt 
     End If 
     RowValidateCrnt = RowValidateCrnt + 1 
     Loop 
    Next 
    End With 

    Debug.Print " Rules per Column table" 
    Debug.Print " C RR RR" 
    For ColValCrnt = ColValMin To ColValMax 
    Debug.Print " " & ColValCrnt & " " & _ 
       Right(" " & ColRule(ColValCrnt).InxRule1, 2) & " " & _ 
       Right(" " & ColRule(ColValCrnt).InxRuleL, 2) 
    Next 
    Debug.Print 
    Debug.Print " Rule table" 
    Debug.Print " I VV VV CC CC" 
    For InxRuleCrnt = 1 To UBound(Rule) 
    Debug.Print " " & InxRuleCrnt & " " & _ 
         Right(" " & Rule(InxRuleCrnt).InxValue1, 2) & " " & _ 
         Right(" " & Rule(InxRuleCrnt).InxValueL, 2) & " " & _ 
         Right(" " & Rule(InxRuleCrnt).InxCond1, 2) & " " & _ 
         Right(" " & Rule(InxRuleCrnt).InxCondL, 2) & " " 
    Next 
    Debug.Print 
    Debug.Print " Condition table" 
    Debug.Print "  I C VV VV" 
    For InxCondCrnt = 1 To UBound(Cond) 
    Debug.Print " " & Right(" " & InxCondCrnt, 2) & " " & _ 
         Cond(InxCondCrnt).Col & " " & _ 
         Right(" " & Cond(InxCondCrnt).InxValue1, 2) & " " & _ 
         Right(" " & Cond(InxCondCrnt).InxValueL, 2) 
    Next 
    Debug.Print 
    Debug.Print " Value table" 
    Debug.Print " "; 
    For InxValueCellCrnt = 1 To UBound(ValueCell) 
    Debug.Print "E" & Right(" " & InxValueCellCrnt, 2) & "=" & _ 
       Left(ValueCell(InxValueCellCrnt) & " ", 5); 
    If (InxValueCellCrnt Mod 10) = 0 Then 
     Debug.Print 
     Debug.Print " "; 
    End If 
    Next 

End Subの

+0

この説明に感謝します。私はそれを試してみて、私はあなたに戻ってきます –

0

名前付き範囲を使用する場合は、INDEXおよびCOUNTA式を使用して名前付き範囲を動的にする必要があります。こうすることで、リストにレコードを追加することができ、名前付き範囲は自動的に調整されます。しかし次に、名前付き範囲を使用しないように伝えます。

この種のリンクされたデータ検証は、単純なリンクリストには適しています。しかし、あなたの状況は単純ではありません。あなたはDVからActiveXコントロールに移動する必要があると思います。

複雑なレベルがいくつかあります。あなたが今持っているものが一方的にあります。もう一方の端には、データベース内にすべてのものがあり、Excelは適切なリレーショナルデータベースの計算エンジン/フロントエンドです。あなたはおそらくそれらの2つの中間に終わるでしょう。

本当に関連性の高い詳細な回答を得るための十分な情報がないため、私はたくさんの仮定を行い、あなたの状況に合わないときを認識しなければなりません。私はあなたがデータ入力を処理するためにユーザーフォームを作成する必要があると思います。ユーザーフォーム上のリストボックス/コンボボックスは、コードを通じて動的に更新されます。ユーザーフォームは、リボンを介して、右クリックメニューを介して、または「編集」ハイパーリンクを介して呼び出されます。ユーザーフォームは現在選択されている行を入力します。

次に、コピーアンドペーストのオプションがあります。ユーザーは、個々の項目をコピーしてユーザーフォームに貼り付けることができ、コードはそれらを検証します。あるいは、コードが検証する情報の全レコードをコピーすることもできます。

アクセスをバックエンドとして恥じてはなりません。私のプロジェクトのほとんどは、Excelによって制御されるJetデータベースです。 Excelは、計算エンジン、入力メカニズム、およびレポートメカニズムです。

+0

は、私がアクセスを使用していない唯一の理由はので、私は私の1行が持っているので、行データで行を追加するためのユーザーフォームを使用するカントit..secondlyに精通していない私のユーザーである私に信じて約20列を塗りつぶし、ユーザーは個々の列を貼り付けることを望んでいます...私は真剣に名前付き範囲に固執したくありませんが、どうやって簡単に動的にすることができるのか説明できますか? –

関連する問題