Вам нужна функция FIND() и / или SEARCH() . 
Использование:
      FIND(find_text, within_text)
                                                                  возвращает начальную позицию первой текстовой строки
                                                                  во второй текстовой строке (начиная с позиции 1)
Таким образом, FIND("lunch", "lunch with customer") возвращает 1, а FIND("lunch", "business lunch") возвращает 10. 
Если первая строка не найдена во второй, это возвращает # #VALUE! значение ошибки. 
SEARCH() похож на FIND() за исключением того, что FIND() чувствителен к регистру, а SEARCH() - нет.  Так
      FIND("lunch", "Lunch with customer")     возвращает # #VALUE!
  но
      SEARCH("lunch", "Lunch with customer")   возвращает 1
Я предполагаю, что вы захотите использовать SEARCH() , без учета регистра.
Вы захотите настроить массив следующим образом:
                                                        
Вероятно, лучше сделать это на отдельном листе; давайте назовем это Key-Sheet . 
Затем на листе данных: если описание в свободной форме находится в столбце A (начиная с ячейки A1), введите в ячейку B1:
=MATCH(MIN(IFERROR(SEARCH('Key-Sheet'!$A$1:$A$7,$A1),LEN($A1)+1)), SEARCH('Key-Sheet'!$A$1:$A$7,$A1))
и нажмите Ctrl+Shift+Enter, чтобы сделать его «формулой массива». 
(Он будет отображаться в строке формул в фигурных скобках.) 
Объяснение:
SEARCH('Key-Sheet'!$A$1:$A$7,$A1) - для каждого ключевого слова из столбца A таблицы ключей ("кофе", "обед", "ужин" и т.д.) Найдите его в описании в текущей строке, столбец A таблицы данных (например, «бизнес-ланч»). 
Это создаст массив, содержащий { #VALUE!; 10 ; #VALUE!; …} (Семь элементов (в этом примере), по одному на ключевое слово; второй показывает результат для "ланча", который находится в 'Key-Sheet'!A2). 
IFERROR(…,LEN($A1)+1) - замените # #VALUE! значения с 15 , которые, будучи LEN("business lunch")+1 , не могут быть допустимым возвращаемым значением из SEARCH() (и которое, фактически, выше любого возможного действительного возвращаемого значения из SEARCH()), но который является действительным числом. 
Итак, теперь наш массив { 15 ; 10 ; 15 ; …} 
MIN(…) - извлечь минимальное значение из массива: в данном примере 10 . 
В общем, это будет (первый) успешный возврат из SEARCH() . 
=MATCH(…, …) - обратите внимание, что второй параметр MATCH() такой же, как и первый пункт выше. 
Итак, мы ищем 10 в массиве { #VALUE!; 10 ; #VALUE!; …} 
Это возвращает позицию 10 , то есть 2, что соответствует тому факту, что A1 на листе данных («бизнес-ланч») содержит "обед", который находится во 2-й строке таблицы ключей. 
Чтобы получить категорию расходов, достаточно просто внести указатель в столбец B таблицы. 
Установите для ячейки C1 значение =OFFSET('Key-Sheet'!$B$1,B1-1,0) . 
(Это не обязательно должна быть формула массива.)
                                
Обратите внимание (как указано выше), что, если описание расхода содержит несколько ключевых слов, будет найдено только первое.
Если вы не хотите беспокоиться о промежуточном значении, вы можете просто вычислить
=OFFSET('Key-Sheet'!$B$1,MATCH(MIN(IFERROR(SEARCH('Key-Sheet'!$A$1:$A$6,$A1),LEN($A1)+1)),SEARCH('Key-Sheet'!$A$1:$A$6,$A1))-1,0)
Это должно быть формулой массива.
PS функции FIND() и SEARCH() имеют необязательный третий аргумент:
  SEARCH(find_text, within_text, [start_num])
Так
      SEARCH("cigar", "Sometimes a cigar is just a cigar.")       возвращает 13
  но
      SEARCH("cigar", "Sometimes a cigar is just a cigar.", 17)   возвращается 29
Я не вижу смысла для вас использовать его.