***WINNERS ANNOUNCEMENT*** June/July 2008 Challenge of the Month

Re: June/July 2008 Challenge of the Month

--- the arguments of archie() are the cells in Column A

Function archie(TmpRng As Range) As String
For i = 2 To Application.WorksheetFunction.CountA(Range("D:D"))
If InStr(TmpRng.Text, Cells(i, 4)) > 0 Then archie = Cells(i, 5)
Next i
' this last line is smth like the #N/A you would get w / vlookup
If archie = "" Then archie = "archie is tired of looking"
End Function
 

Excel Facts

When they said...
When they said you are going to "Excel at life", they meant you "will be doing Excel your whole life".
Re: June/July 2008 Challenge of the Month

Why not a combination of a formula and VBA to make the solution easier to maintain:

Formula:
=VLOOKUP(ExtractColor(A2;$D$2:$D$10);D$2:$E$10;2;0)


VBA:

Private Function ExtractColor(sValue As String, rColors As Range) As Variant

Dim sColor As String
Dim rCell As Range

'Look for the color in sValue based on the colors in range rColors
For Each rCell In rColors
If InStr(1, sValue, rCell.Text, vbTextCompare) > 0 Then
'Color found
sColor = rCell.Text
Exit For
End If
Next

'Return color or error
ExtractColor = IIf(sColor = vbNullString, CVErr(xlErrNA), sColor)

End Function
 
Re: June/July 2008 Challenge of the Month

And another UDF :

Code:
Public Function AssignTo(Phrase As Range, KeywordsRange As Range) As String

Dim vKeyword As Variant
Dim vCheck As Variant

    For Each vKeyword In KeywordsRange
        vCheck = InStr(Phrase, vKeyword.Value)
        If vCheck > 0 Then
            AssignTo = vKeyword.Offset(0, 1).Value
            Exit Function
        End If
    Next vKeyword

End Function
 
Re: June/July 2008 Challenge of the Month

I didn't read the submission requirements and made a sort of 'whole house' solution before reading this thread. I sent it to mrexcel.com. My mistake. If you are interested in a vba only approach (from my humble thought process that is...), I can post the code although it is kind of formal and pretty darned long. Includes a couple buttons on sheet1. One button to process the lists, the other to reset (unprocess) the lists. I can email the spreadsheet too since we can't use attachments here.

Basically, I look for column headers, id the columns, complain about a missing column, get the extents of the list in each column, complain about an empty list, mark missing elements in a list with colored frames and '???', note more than one color in a phrase, try to catch colors with embedded parts of other color names eg, with bluegray, process the whole word and not just the blue part.

All vba approach minimal use of built-in excel methods. (in my experience Vba itself was less prone to changes than the application specific extensions)

Robert Phillips
Westlake, Ohio
 
Re: June/July 2008 Challenge of the Month

Here is the VBA code,

For keywordIndex = 2 To .Cells(.Rows.Count, 4).End(xlUp).Row
strKeyword = .Cells(keywordIndex, .Range("Keyword").Column).Value
If VBA.Trim(strKeyword) <> "" Then
For PharseIndex = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
If VBA.InStr(1, .Cells(PharseIndex, 1).Value, strKeyword, vbTextCompare) > 0 Then
.Cells(PharseIndex, 2).Value = .Cells(keywordIndex, 4).Offset(0, 1).Value
End If
Next
End If
Next

Thanks
Tennison
 
Re: June/July 2008 Challenge of the Month

A second try at posting a piece of the output from the processed lists....
challengejune2008.rlp.xls
ABCDE
10yellow is my favorite color????MarymagentaJenny
11I like his pink shirt??Fredgreen
12pink is my favorite color??????FredJerry
13the ocean is orange????RalphgrayMr. Ed
14I like his orange shirtRalphbluegrayTomBob
15the grass is greener???
16orange is my favorite color????Ralph
17the ocean is brown?????Lora
18I like his brown shirt?Lora
19brown is my favorite color?????Lora
20the ocean is white?????Tracy
21I like his white shirt?Tracy
22white is my favorite color?????Tracy
23hops are green???
24the ocean is lavendar??Earl
25I like his lavendar shirt??????Earl
26magenta tie and pink shirtJenny ##
27wear the bluegray hatTomBob
28the sun is gold???
29???
30bring the gray shirtMr. Ed
Sheet1
 
Re: June/July 2008 Challenge of the Month

I'm starting to get the hang of working with board. Here's the MODULE code.

Rich (BB code):
'ASSUMPTIONS: LISTS ON ACTIVESHEET

Option Explicit
Option Compare Text

Const None = -4142
Const White = 2
Const BriteRed = 3
Const BriteGreen = 4
Const Blue = 5
Const BriteYel = 6
Const Magenta = 7
Const Cyan = 8
Const Darkred = 9
Const DarkGreen = 10
Const LtBlue = 34
Const LtGreen = 35
Const ToolTip = 36
Const Pink = 38
Const Violet = 39
Const Tan = 40
Const Teal = 42
Const LimaBean = 43
Const Pumpkin = 44
Const Orange = 45
Const Wine = 54

Type PhraseAssign
  Phrase As String  'the phrase
  Color As String   'the keyword
  Name As String    'the assignment
End Type

Type KeyAssign
  Color As String  'the keyword
  Name As String   'the assignee
End Type

Public ProcessRun As Boolean
Private OkToProcess As Boolean

Private LastPhrase As Long
Private LastPhraseAssign As Long
Private LastKeyWord As Long
Private LastKeyAssign As Long

Private ModuleName$
'PhraseCol 1, PhraseAssignCol 2, KeyWordCol 3, KeyAssignCol 4
Private FieldCols(1 To 4) As String

Private PhraseAssignments() As PhraseAssign
Private KeyAssignments() As KeyAssign
Private KeyOrder() As KeyAssign

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Public Sub ProcessAllLists()
  On Error GoTo BeSafe
  
  Application.ScreenUpdating = False
  ModuleName$ = "ProcessAllLists"
  
  FindColumnHeaders
  If OkToProcess Then
    FindListExtents
    If OkToProcess Then
      ProcessKeywords
      If OkToProcess Then
        ProcessPhrases
      End If
    End If
  End If
  
  If Not OkToProcess Then
    MsgBox "Please make corrections."
  End If
  
  StepOut
  Application.ScreenUpdating = True
  Exit Sub
  
BeSafe:
  ErrorHandler

End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Public Sub UnProcessLists()
  Dim i As Integer
  Dim Row1$, Row2$
  
  On Error GoTo BeSafe
  ModuleName$ = "UnProcessLists"
    
  Row1$ = "2"
  Row2$ = CStr(LastPhraseAssign)
  Range(FieldCols(2) & Row1$ & ":" & FieldCols(2) & Row2$).ClearFormats
  Range(FieldCols(2) & Row1$ & ":" & FieldCols(2) & Row2$).ClearContents
  Row2$ = CStr(LastKeyWord)
  Range(FieldCols(3) & Row1$ & ":" & FieldCols(3) & Row2$).ClearFormats
  Row2$ = CStr(LastKeyAssign)
  Range(FieldCols(4) & Row1$ & ":" & FieldCols(4) & Row2$).ClearFormats
  
  StepOut
  Exit Sub

BeSafe:
  ErrorHandler

End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
'ASSUMPTIONS: Headers on Row 1
Private Sub FindColumnHeaders()
  Dim GotField(1 To 4) As Boolean
  Dim i, j, LastCol As Integer
  Dim FieldNames(1 To 4), TmpCol As String
  
  On Error GoTo BeSafe
  ModuleName$ = "FindColumnHeaders"
  
  'Look for similar, give a little leeway to user
  FieldNames(1) = "Phrase"
  FieldNames(2) = "Assigned"
  FieldNames(3) = "Keyword"
  FieldNames(4) = "Assignee"
  'rely on vbcompiler to init booleans to false
  
  With ActiveSheet
    .Range("IV1").Select
    Selection.End(xlToLeft).Select
    LastCol = Selection.Column
    
    Select Case LastCol
      Case Is < 4
        MsgBox "You seem to be missing a necessary data column." & vbCrLf & "This worksheet should contain 4 columns with headers." & vbCrLf & "They should be 'Phrases', 'Assigned To', 'Keyword', and 'Assignee' (person name)."
        OkToProcess = False
        Exit Sub
      
      Case Else
        For i = 1 To LastCol
          TmpCol = NumToLtr(i)
          For j = 1 To 4
            If InStr(1, Range(TmpCol & "1").Value, FieldNames(j)) > 0 Then
              If GotField(j) = True Then  'uh oh, already had one by that name
                MsgBox "It appears there are two columns with similar field names. Please correct."
                OkToProcess = False
                Exit Sub
              Else
                FieldCols(j) = TmpCol
                GotField(j) = True
                Exit For
              End If
            End If
          Next
          'loop not worth it
          OkToProcess = GotField(1) And GotField(2) And GotField(3) And GotField(4)
          If OkToProcess Then Exit For  'take first 4 qualifiers by default
        Next
    End Select
  End With
  
  Exit Sub
  
BeSafe:
  ErrorHandler
    
End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Private Sub FindListExtents()
  Dim i As Long
  Dim Row$
  
  On Error GoTo BeSafe
  ModuleName$ = "FindListExtents"
  
  With ActiveSheet
    '1 LastPhrase, 2 LastPhraseAssign, 3 LastKeyWord, 4 LastKeyAssign
    Range(FieldCols(1) & "65536").Select
    Selection.End(xlUp).Select
    LastPhrase = Selection.Row
    If LastPhrase < 2 Then
      MsgBox "There are no phrases to process."
      OkToProcess = False
      Exit Sub
    Else
      LastPhraseAssign = Selection.Row
    End If
    
    Range(FieldCols(3) & "65536").Select
    Selection.End(xlUp).Select
    LastKeyWord = Selection.Row
    If LastKeyWord < 2 Then
      MsgBox "There are no keywords to process."
      OkToProcess = False
      Exit Sub
    End If
    
    Range(FieldCols(4) & "65536").Select
    Selection.End(xlUp).Select
    LastKeyAssign = Selection.Row
    If LastKeyAssign < 2 Then
      MsgBox "There is no one assigned to the keywords."
      OkToProcess = False
      Exit Sub
    End If
    
  End With

  'normalize
  If LastKeyWord > LastKeyAssign Then
    LastKeyAssign = LastKeyWord
  Else
    LastKeyWord = LastKeyAssign
  End If
    
  ReDim PhraseAssignments(2 To LastPhrase)
  ReDim KeyAssignments(2 To LastKeyWord)
  
  With ActiveSheet
    For i = 2 To LastPhrase
      Row$ = CStr(i)
      'if someone left a blank inside the phrase list
      PhraseAssignments(i).Phrase = Trim$(.Range(FieldCols(1) & Row$).Value)
      If Len(PhraseAssignments(i).Phrase) = 0 Then
        PhraseAssignments(i).Phrase = "???"
      End If
    Next
    
    For i = 2 To LastKeyWord   'row 1 field names
      Row$ = CStr(i)
      KeyAssignments(i).Color = Trim$(.Range(FieldCols(3) & Row$).Value)
      KeyAssignments(i).Name = Trim$(.Range(FieldCols(4) & Row$).Value)
      .Range(FieldCols(3) & Row$).Select
      'if someone forgot to put a name with a color or left a blank in the list
      If Len(KeyAssignments(i).Color) = 0 Then
        KeyAssignments(i).Color = "???"
      End If
      .Range(FieldCols(4) & Row$).Select
      If Len(KeyAssignments(i).Name) = 0 Then
        KeyAssignments(i).Name = "???"
      End If
    Next
  End With

  'Clean Up Any Prior Processing, unmark cells, clear assigned to list
  UnProcessLists
  
  'POSTPROCESS to COLOR FRAMES
  With ActiveSheet
    For i = 2 To LastKeyWord
      Row$ = CStr(i)
      If KeyAssignments(i).Color = "???" Then
        .Range(FieldCols(3) & Row$).Select
        FrameCell Teal
      End If
      If KeyAssignments(i).Name = "???" Then
        .Range(FieldCols(4) & Row$).Select
        FrameCell Teal
      End If
    Next
  End With
  
  Exit Sub

BeSafe:
  ErrorHandler

End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Private Sub ProcessKeywords()
  Dim OrderChanged As Boolean
  Dim i, j, k, Longest, TmpLen1, TmpLen2, TmpOrder1 As Integer
  Dim Order() As Integer
  
  'CREATE ORDERED LIST OF LONGEST COLOR NAME TO SHORTEST COLOR NAME
  'USED TO LOCATE CORRECT COLORNAME IN PHRASE WHEN TWO OR MORE COLOR NAMES
  'HAVE THE SAME SUB PARTS LIKE BLUE AND BLUEGRAY. CHECK FOR BLUEGRAY FIRST
  
  On Error GoTo BeSafe
  ModuleName$ = "ProcessKeywords"
  
  OkToProcess = True
  
  ReDim Order(2 To LastKeyWord, 2) As Integer
  
  For i = 2 To LastKeyWord          'current user order
    Order(i, 1) = Len(KeyAssignments(i).Color) 'colorname length
    Order(i, 2) = i                            'current order on list
  Next
  
  For i = 2 To UBound(Order)
    TmpLen1 = Order(i, 1)   'current length
    OrderChanged = False
    For j = i To UBound(Order)
      TmpLen2 = Order(j, 1) 'next length
      If TmpLen2 > TmpLen1 Then
        TmpLen1 = TmpLen2
        OrderChanged = True
        Longest = j         'list pointer
      End If
    Next
    If OrderChanged Then
      TmpLen1 = Order(Longest, 1)      'color length
      TmpOrder1 = Order(Longest, 2)    'list position pointer
      Order(Longest, 1) = Order(i, 1)  'move smaller up to longest
      Order(Longest, 2) = Order(i, 2)  'move listpointer with it
      Order(i, 1) = TmpLen1            'move longest to beginning
      Order(i, 2) = TmpOrder1          'move listpointer with it
    End If
  Next
  
  ReDim KeyOrder(2 To LastKeyWord)
  
  For i = 2 To LastKeyWord
    KeyOrder(i).Color = KeyAssignments(Order(i, 2)).Color
    KeyOrder(i).Name = KeyAssignments(Order(i, 2)).Name
  Next
  
  Exit Sub

BeSafe:
  ErrorHandler

End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Private Sub ProcessPhrases()
  Dim GotColor As Boolean
  Dim KeyLen, KeyStart, PhraseLen As Integer
  Dim i, j, k As Long
  Dim Row$
  
  On Error GoTo BeSafe
  ModuleName$ = "ProcessPhrases"
  
  With ActiveSheet
    For i = 2 To LastPhrase
      Row$ = CStr(i)
      GotColor = False
      If PhraseAssignments(i).Phrase <> "???" Then
        For j = 2 To LastKeyWord
          KeyStart = InStr(1, PhraseAssignments(i).Phrase, KeyOrder(j).Color)
          If KeyStart > 0 Then
            GotColor = True
            PhraseAssignments(i).Name = KeyOrder(j).Name
            .Range(FieldCols(2) & Row$).Value = PhraseAssignments(i).Name
            If PhraseAssignments(i).Name = "???" Then
              .Range(FieldCols(2) & Row$).Select
              FrameCell DarkGreen
            End If
            For k = 2 To LastKeyWord
              'now check the other colors too...
              If k <> j Then
                If InStr(1, KeyOrder(j).Color, KeyOrder(k).Color) = 0 Then
                  '(k)Color isn't a subpart of a longer colorname (j)Color
                  'so go ahead and test for a second color
                  If InStr(1, PhraseAssignments(i).Phrase, KeyOrder(k).Color) > 0 Then
                    'uh oh, two+ colors
                    .Range(FieldCols(2) & Row$).Select
                    .Range(FieldCols(2) & Row$).Value = .Range(FieldCols(2) & Row$).Value & " ##"
                    FrameCell Orange
                    Exit For
                  End If
                End If
              End If
            Next
            Exit For
          End If
        Next
        'uh oh, no keyword color associated with phrase
        If Not GotColor Then
          .Range(FieldCols(2) & Row$).Select
          .Range(FieldCols(2) & Row$).Value = "???"
           FrameCell DarkGreen
        End If
      Else
        'a blank phrase in the list
        .Range(FieldCols(2) & Row$).Select
        .Range(FieldCols(2) & Row$).Value = "???"
        FrameCell DarkGreen
      End If
    Next
  End With
  
  Exit Sub
  
BeSafe:
  ErrorHandler

End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Private Sub StepOut()
  Dim i As Integer
  
  For i = 1 To 256
    If Len(Trim(Cells(1, i).Value)) = 0 Then
      Cells(1, i).Select
      Exit For
    End If
  Next
End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Private Sub FrameCell(HiliteColor)
  
  With Selection.Borders(xlEdgeLeft)
    .LineStyle = xlContinuous
    .Weight = xlMedium
    .ColorIndex = HiliteColor
  End With
  
  With Selection.Borders(xlEdgeTop)
    .LineStyle = xlContinuous
    .Weight = xlMedium
    .ColorIndex = HiliteColor
  End With
  
  With Selection.Borders(xlEdgeBottom)
    .LineStyle = xlContinuous
    .Weight = xlMedium
    .ColorIndex = HiliteColor
  End With
  
  With Selection.Borders(xlEdgeRight)
    .LineStyle = xlContinuous
    .Weight = xlMedium
    .ColorIndex = HiliteColor
  End With
    
End Sub

'ASSUMPTIONS: LISTS ON ACTIVESHEET
Private Sub UnFrameCell()
  With Selection.Borders(xlEdgeLeft)
    .LineStyle = xlNone
  End With
  
  With Selection.Borders(xlEdgeTop)
    .LineStyle = xlNone
  End With
    
  With Selection.Borders(xlEdgeRight)
    .LineStyle = xlNone
  End With
    
  With Selection.Borders(xlEdgeBottom)
    .LineStyle = xlNone
  End With
End Sub

Private Function NumToLtr(Num) As String
  Dim Letter1 As Integer, Letter2 As Integer
  
  Letter2 = (Num Mod 26)
  Letter1 = Int(Num / 26) + (Letter2 = 0)
  Letter2 = -(Letter2 = 0) * 26 + Letter2
  If Letter1 > 0 Then
    NumToLtr = Chr(Letter1 + 64)
  End If
  NumToLtr = NumToLtr & Chr(Letter2 + 64)

End Function

Private Sub ErrorHandler()
  
  MsgBox "Processing was interrupted in Module:" & ModuleName$ & vbCrLf & Err.Description
  Err.Clear
  OkToProcess = False
  Application.ScreenUpdating = True

End Sub



Here's SHEET1 code for 2 command buttons named: ProcessLists and Reset

Rich (BB code):
Option Explicit
Option Compare Text

Private Sub ProcessLists_Click()
  ProcessAllLists
  ProcessRun = True
  Application.ScreenUpdating = True 'just in case
End Sub

Private Sub Reset_Click()
  If ProcessRun Then
    UnProcessLists
    ProcessRun = False
  Else
    'have to setup arrays first
    MsgBox "Please run Process Lists first...."
  End If
  Application.ScreenUpdating = True 'necessary
End Sub
 
Re: June/July 2008 Challenge of the Month

Hi Mr. Jelen
Please look at this Macro in response to your "Challenge of the Month Jun / Jul 2008"
Warm Regards


Sub Macro1()

' Macro recorded 7/4/2008 by INDIARAVI

Dim KWend As Long, i As Long, Phrase As String, KW As String, PhraseEnd As Long, j As Long, WSEnd As Long
WSEnd = Range("A1").End(xlDown).Row + 1
KWend = Range("D" & WSEnd).End(xlUp).Row
PhraseEnd = Range("A" & WSEnd).End(xlUp).Row
For i = 2 To KWend
KW = Range("D" & i).Value
For j = 2 To PhraseEnd
Phrase = Range("A" & j).Value
If InStr(Phrase, KW) > 0 Then
Range("B" & j).Value = Range("E" & i).Value
End If
Next j
Next i
End Sub
 

Forum statistics

Threads
1,214,872
Messages
6,122,025
Members
449,060
Latest member
LinusJE

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