Assinging variables? Approach needed...

maykinit

New Member
Joined
Jan 19, 2009
Messages
31
****** http-equiv="Content-Type" content="text/html; charset=utf-8">****** name="ProgId" content="Word.Document">****** name="Generator" content="Microsoft Word 11">****** name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CMARK%7E1.GAR%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:8.5in 11.0in; margin:1.0in 1.25in 1.0in 1.25in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]--> The problem:
I have a spreadsheet containing a column of data similar to the below example. This column contains some 200plus lines.
AA
BB
CC
DD
EE
Etc…
<o:p> </o:p>
A user of this application would enter a code…
IE: 123456789-DDAABBEECC
From this code I need to be able to determine what series of values follow the dash and whether or not they are appropriate for the code through a series of rules.
So I need to write a series of “rules”. An example of a rule would be IF AND OR's or lookups for things like "if DD and EE are both contained within the same code then the code is not valid". Any combination of those 200+ values coming from the spreadsheet column could conceivably end up in the coding and in any order following the "-"dash.
I have parsed the code the user enters for the values that follow the “-“dash.
I’m thinking there is a really easy solution to this but damned if I can come up with it.:confused: I'm hoping I've provide enough detail of the problem here but please let me know if more is needed.
I have tried a number of different methodologies all with little success. I would sincerely appreciate any help and/or guidance the gurus here might provide me. I am facing a quickly approaching closing deadline on this one and trust me, your help would be greatly appreciated. The more detail the better, please?. A sincere thanks to the solution provider.

<o:p> </o:p>
-M
 

Excel Facts

How to create a cell-sized chart?
Tiny charts, called Sparklines, were added to Excel 2010. Look for Sparklines on the Insert tab.
Hi,

Is each element of the code 2 characters long, and could you work with a rules table looking something like:
Excel Workbook
AB
1ConditionValid?
2DD&EEFALSE
3FF&GG/HHFALSE
4AA&DDTRUE
Rules
Excel 2003
'&' and '/' are equivalent to AND and OR, and the expression would be evaluated from left to right
 
Last edited:
Upvote 0
OK, i KNOW this is a tad late & that you've probably sorted your problem now anyway, but I've developed a RuleLookup function
Yesterday 'FuzzyVlookup, Today RuleLookup, tomorrow the world (evil laughter) :)

This function is similar to VLookup, but instead of a simple value, a rule table is supplied.
Rules consist of one or more conditions, seperated by 'AND' or 'OR', brackets may be used to clarify the evaluation order.

conditions consist of:
  • an optional 'Not'
  • optional comparison operators '<', '<=', '=','<>', @>=', '>', if omitted, '=' is assumed
  • A mandatory value, optionally enclosed by single or double quotes

The Call is RuleLookup(Lookup_Value, Rule_Table,Return_Column)
The lookup Value is the value to be evaluated
The Rule Table consists of a set of rules in column A, and one or more data columns.
The Return_Column specifies the column of the cell to be returned for the matching rule.

Example:
Excel Workbook
ABCDEF
1RuleReturn ValueUser CodeExtractedRuleLookup
2contains dd and contains eecontains dd and contains ee123456789-DDAABBEECCDDAABBEECCcontains dd and contains ee
3contains dd and not contains eecontains dd and not contains ee123456789-DDAABBZZCCDDAABBZZCCcontains dd and not contains ee
4contains zz and (contains ff or contains gg)contains zz and (contains ff or contains gg)123456789-AABBZZCCAABBZZCC#N/A
5123456789-AABBZZffCCAABBZZffCCcontains zz and (contains ff or contains gg)
6123456789-AABBZZCCGGAABBZZCCGGcontains zz and (contains ff or contains gg)
Sheet1
Excel 2003
Cell Formulas
RangeFormula
E2=RIGHT(D2,LEN(D2)-FIND("-",D2))
E3=RIGHT(D3,LEN(D3)-FIND("-",D3))
E4=RIGHT(D4,LEN(D4)-FIND("-",D4))
E5=RIGHT(D5,LEN(D5)-FIND("-",D5))
E6=RIGHT(D6,LEN(D6)-FIND("-",D6))
F2=rulelookup(E2,$A$2:$B$4,2)
F3=rulelookup(E3,$A$2:$B$4,2)
F4=rulelookup(E4,$A$2:$B$4,2)
F5=rulelookup(E5,$A$2:$B$4,2)
F6=rulelookup(E6,$A$2:$B$4,2)
B2=A2
B3=A3
B4=A4


columns A,B contain the rule table
Column E contains the extracted string to be entered into the RuleLookup function

Column F are the RuleLookup calls.

For this example, the value (if a matching rule is satisfied) is merely a copy of the rule itself.

Here is the code:
Code:
Option Explicit
Const mlMask_Starts As Long = 1
Const mlMask_Contains As Long = 2
Const mlMask_Ends As Long = 4
Const mlMask_Less As Long = 8
Const mlMask_Equals As Long = 16
Const mlMask_Greater As Long = 32

Public Enum TypeOfElement
    Type_Unassigned = -1
    Type_Condition = 0  'T F
    Type_Operator = 1   ' 'AND' 'OR' & /
    Type_Bracket = 2    ' ( )
End Enum

Public Type ElementDesc
    ElementType As TypeOfElement
    Value As String
    ' The following are only applicable for 'element type 'Condition'
    NegateComparison As Boolean 'True if 'NOT'
    Comparator As Long       'Bit significant 'starts', 'contains', 'Ends',<,<=, =,<>, >=, >
End Type

Public Function RuleLookup(ByVal LookupValue As String, _
                            ByRef RuleTable As Range, _
                            Optional ResultsColumn As Integer = 2) As Variant

Dim bEvaluation As Boolean
Dim iElementPtr As Integer
Dim iCurElementPtr As Integer, iPtr1 As Integer, iLen As Integer
Dim lRuleRow As Long
Dim lComparator As Long, lCurEvaluation As Long
Dim sLookupValue As String
Dim sCurRule As String, sChar As String, sCurDelim As String, sCurValue As String
Dim sCurRuleString As String, sCurRuleRPN As String
Dim uCurElement As ElementDesc, uaElements() As ElementDesc
Dim vaRuleTable() As Variant
Dim vResult As Variant

'-- Normalise & validate LookupValue parameter --
sLookupValue = LCase$(LookupValue)
If sLookupValue = "" Then
    RuleLookup = "*** LookupValue is null ***"
    Exit Function
End If

'-- Validate ResultsColumn parameter --
If ResultsColumn< 2 Then
    RuleLookup = "*** 'ResultsColumn' must be > 1 ***"
    Exit Function
End If

'-- Store Rules Table into array & validate RuleTable parameter --
vaRuleTable = Intersect(RuleTable, Sheets(RuleTable.Parent.Name).UsedRange).Value
If UBound(vaRuleTable, 2)< ResultsColumn Then
    RuleLookup = "*** Rules table must be at least " & ResultsColumn & " wide ***"
    Exit Function
End If

'-- Loop thru rules --
For lRuleRow = 1 To UBound(vaRuleTable, 1)
    sCurRule = Trim$(LCase$(CStr(vaRuleTable(lRuleRow, 1))))
    iCurElementPtr = 0
    iElementPtr = 0
    
    InitialiseElement uCurElement
    iCurElementPtr = 1
    Do While iCurElementPtr<= Len(sCurRule)
        sChar = Mid$(sCurRule, iCurElementPtr, 1)
        If sChar = " " Then
            
        ElseIf Mid$(sCurRule & "123", iCurElementPtr, 3) = "and" Then
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            uCurElement.ElementType = Type_Operator
            uCurElement.Value = "&"
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            iCurElementPtr = iCurElementPtr + 2
        
        ElseIf InStr("&/", sChar)<> 0 Then
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            uCurElement.ElementType = Type_Operator
            uCurElement.Value = sChar
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
        
        ElseIf Mid$(sCurRule & "12", iCurElementPtr, 2) = "or" Then
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            uCurElement.ElementType = Type_Operator
            uCurElement.Value = "/"
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            iCurElementPtr = iCurElementPtr + 1
            
        ElseIf Mid$(sCurRule, iCurElementPtr, 3) = "not" Then
            uCurElement.NegateComparison = True
            iCurElementPtr = iCurElementPtr + 2
        
        ElseIf sChar = "<" Then
            uCurElement.Comparator = uCurElement.Comparator Or mlMask_Less
            
        ElseIf sChar = "=" Then
            uCurElement.Comparator = uCurElement.Comparator Or mlMask_Equals
            
        ElseIf sChar = ">" Then
            uCurElement.Comparator = uCurElement.Comparator Or mlMask_Greater
            
        ElseIf Mid$(sCurRule & "12345", iCurElementPtr, 5) = "starts" Then
            uCurElement.Comparator = uCurElement.Comparator Or mlMask_Starts
            iCurElementPtr = iCurElementPtr + 4
            
        ElseIf Mid$(sCurRule & "12345678", iCurElementPtr, 8) = "contains" Then
            uCurElement.Comparator = uCurElement.Comparator Or mlMask_Contains
            iCurElementPtr = iCurElementPtr + 7
            
        ElseIf Mid$(sCurRule & "1234", iCurElementPtr, 4) = "ends" Then
            uCurElement.Comparator = uCurElement.Comparator Or mlMask_Ends
            iCurElementPtr = iCurElementPtr + 3
            
        ElseIf InStr("()", sChar)<> 0 Then
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            uCurElement.ElementType = Type_Bracket
            uCurElement.Value = sChar
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
        
        ElseIf InStr("'""", sChar)<> 0 Then
            '-- here if we've got a delimited value --
            If uCurElement.ElementType = Type_Unassigned Then uCurElement.ElementType = Type_Condition
            uCurElement.Value = ""
            sCurDelim = sChar
            For iPtr1 = iCurElementPtr + 1 To Len(sCurRule)
                sChar = Mid$(sCurRule, iPtr1, 1)
                iCurElementPtr = iCurElementPtr + 1
                If sChar = sCurDelim Then Exit For
                uCurElement.Value = uCurElement.Value & sChar
            Next iPtr1
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            
        Else
            '-- Here if we've got a value --
            If uCurElement.ElementType = Type_Unassigned Then uCurElement.ElementType = Type_Condition
            uCurElement.Value = ""
            sCurDelim = ""
            For iPtr1 = iCurElementPtr To Len(sCurRule)
                sChar = Mid$(sCurRule, iPtr1, 1)
                If InStr("() &/", sChar)<> 0 Then
                    iCurElementPtr = iCurElementPtr - 1
                    Exit For
                End If
                iCurElementPtr = iCurElementPtr + 1
                uCurElement.Value = uCurElement.Value & sChar
            Next iPtr1
            AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
            
        End If
        
        iCurElementPtr = iCurElementPtr + 1
    Loop
    If uCurElement.ElementType<> Type_Unassigned Then
        AddElement InputElement:=uCurElement, Pointer:=iElementPtr, ElementArray:=uaElements
    End If
    
    'Evaluate each element in array & store in string
    sCurRuleString = ""
    For iPtr1 = 1 To UBound(uaElements)
        If uaElements(iPtr1).ElementType = Type_Bracket _
        Or uaElements(iPtr1).ElementType = Type_Operator Then
            sCurRuleString = sCurRuleString & uaElements(iPtr1).Value
        ElseIf uaElements(iPtr1).ElementType = Type_Condition Then
            lCurEvaluation = 0
            sCurValue = uaElements(iPtr1).Value
            iLen = Len(sCurValue)
            If iLen<= Len(sLookupValue) Then
                If Left$(sLookupValue, iLen) = sCurValue Then lCurEvaluation = lCurEvaluation Or mlMask_Starts
                If InStr(sLookupValue, sCurValue)<> 0 Then lCurEvaluation = lCurEvaluation Or mlMask_Contains
                If Right$(sLookupValue, iLen) = sCurValue Then lCurEvaluation = lCurEvaluation Or mlMask_Ends
                If sLookupValue = sCurValue Then lCurEvaluation = lCurEvaluation Or mlMask_Equals
            End If
            If sLookupValue< sCurValue Then lCurEvaluation = lCurEvaluation Or mlMask_Less
            If sLookupValue > sCurValue Then lCurEvaluation = lCurEvaluation Or mlMask_Greater
            
            bEvaluation = (lCurEvaluation And uaElements(iPtr1).Comparator)<> 0
            bEvaluation = bEvaluation Xor uaElements(iPtr1).NegateComparison
            If bEvaluation Then
                sCurRuleString = sCurRuleString & "T"
            Else
                sCurRuleString = sCurRuleString & "F"
            End If
        End If
    Next iPtr1
    
    '-- Convert string to RPN --
    sCurRuleRPN = InfixToRPN(sCurRuleString)
    If Left$(sCurRuleRPN, 1) = "*" Then
        RuleLookup = sCurRuleRPN
        Exit Function
    End If
    
    '-- Evaluate RPN Expression. If evaluates to True ir an error message, Return Result & exit --
    vResult = EvaluateRPNExpression(sCurRuleRPN)
    If vResult<> False Then
        If vResult = True Then
            RuleLookup = vaRuleTable(lRuleRow, ResultsColumn)
        Else
            RuleLookup = vResult
        End If
        Exit Function
    End If
        
Next lRuleRow
RuleLookup = CVErr(xlErrNA)

End Function

Private Sub AddElement(ByRef InputElement As ElementDesc, _
                       ByRef Pointer As Integer, _
                       ByRef ElementArray() As ElementDesc)
If InputElement.ElementType<> Type_Unassigned Then
    Pointer = Pointer + 1
    ReDim Preserve ElementArray(0 To Pointer)
    ElementArray(Pointer).ElementType = InputElement.ElementType
    ElementArray(Pointer).Value = InputElement.Value
    ElementArray(Pointer).NegateComparison = InputElement.NegateComparison
    ElementArray(Pointer).Comparator = InputElement.Comparator
End If
InitialiseElement InputElement
End Sub

Private Sub InitialiseElement(ByRef Elementx As ElementDesc)
Elementx.ElementType = Type_Unassigned
Elementx.NegateComparison = False
Elementx.Comparator = 0
Elementx.Value = ""
End Sub

Private Function InfixToRPN(ByVal InfixString As String) As String
'Algorithm:
' Parse InputString.
' > If T or F, pass directly to output string
' > If Open Bracket, Push onto FILO Stack
' > If Close Bracket, discard it & POP operators from stack to Output String ...
'   ... Until we come to an open Bracket, which we discard.
' > If & or /, Pop all operators on stack to output string ...
'   ... Until stack is empty or we encounter an open Bracket ...
'   ... Then push operator onto stack
Dim bError As Boolean
Dim iPtr As Integer, iLen As Integer
Dim sStack As String, sOutputString As String, sCur As String, sCur1 As String

sOutputString = ""
sStack = ""
For iPtr = 1 To Len(InfixString)
    sCur = Mid$(InfixString, iPtr, 1)
    If InStr("TF", sCur)<> 0 Then
        sOutputString = sOutputString & sCur
    ElseIf sCur = "(" Then
        sStack = sStack & sCur
    ElseIf sCur = ")" Then
        sOutputString = sOutputString & PopStack(sStack)
        If Left$(sStack, 1) = "*" Then
            InfixToRPN = sStack
            Exit Function
        End If
    ElseIf InStr("&/", sCur)<> 0 Then
        sOutputString = sOutputString & PopStack(sStack)
        If Left$(sStack, 1) = "*" Then
            InfixToRPN = sStack
            Exit Function
        End If
        sStack = sStack & sCur
    End If
Next iPtr
sOutputString = sOutputString & PopStack(sStack)
InfixToRPN = sOutputString
End Function

Private Function PopStack(ByRef Stack As String) As String
Dim iLen As Integer
Dim sCur As String

PopStack = ""
Do
    If Len(Stack) = 0 Then Exit Function
    
    sCur = Right$(Stack, 1)
    If sCur<> "(" Then PopStack = PopStack & sCur
    iLen = Len(Stack)
    If iLen > 1 Then
        Stack = Left$(Stack, iLen - 1)
    Else
        Stack = ""
    End If
Loop While sCur<> "("
End Function

Private Function EvaluateRPNExpression(ByVal RPNString As String) As Variant
'------------------------------------------------------------------------------------
'-- Evaluate RPN Expression. If evaluates to True, Return Result & exit            --
'-- Evaluation rules taken from a web site:-                                       --
'-- While there are input tokens left                                              --
'--   Read the next token from input.                                              --
'--                                                                                --
'--   If the token is a value                                                      --
'--      Push it onto the stack.                                                   --
'--                                                                                --
'--   Otherwise, the token is a function.                                          --
'--     (Operators, like +, are simply functions taking two arguments.)            --
'--      It is known that the function takes n arguments.                          --
'--      So, pop the top n values from the stack.                                  --
'--         If there are fewer than n values on the stack                          --
'--            (Error) The user has not input sufficient values in the expression. --
'--      Evaluate the function, with the values as arguments.                      --
'--      Push the returned results, if any, back onto the stack.                   --
'--                                                                                --
'--   If there is only one value in the stack                                      --
'--      That value is the result of the calculation.                              --
'--   If there are more values in the stack                                        --
'--      (Error) The user input too many values.                                   --
'------------------------------------------------------------------------------------
Dim bResult As Boolean
Dim iPtr As Integer, iLen As Integer
Dim sStack As String, sCur As String
Dim sToken1 As String, sToken2 As String

For iPtr = 1 To Len(RPNString)
    '-- Get next token --
    sCur = Mid$(RPNString, iPtr, 1)
    
    '-- Test if True or False token --
    If InStr("TF", sCur)<> 0 Then
        sStack = sStack & sCur
    Else
        iLen = Len(sStack)
        If iLen< 2 Then
            'We have a problem!
            EvaluateRPNExpression = "*** Illformed Expression ***"
            Exit Function
        End If
        sToken2 = Right$(sStack, 1)
        sStack = Left$(sStack, iLen - 1)
        iLen = iLen - 1
        sToken1 = Right$(sStack, 1)
        If iLen > 1 Then
            sStack = Left$(sStack, iLen - 1)
        Else
            sStack = ""
        End If
        If sCur = "/" Then
            bResult = sToken1 = "T" Or sToken2 = "T"
        Else
            bResult = sToken1 = "T" And sToken2 = "T"
        End If
        If bResult Then
            sStack = sStack & "T"
        Else
            sStack = sStack & "F"
        End If
    End If
Next iPtr

If Len(sStack)<> 1 Then
     EvaluateRPNExpression = "*** Illformed Expression ***"
ElseIf sStack = "T" Then
    EvaluateRPNExpression = True
Else
    EvaluateRPNExpression = False
End If
End Function
 
Upvote 0

Forum statistics

Threads
1,215,043
Messages
6,122,816
Members
449,095
Latest member
m_smith_solihull

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top