Недавно на созвоне финансовый аналитик показывал мне свою Excel-модель. Двенадцать листов, формулы ссылаются друг на друга чере�� три уровня вложенности, именованные диапазоны вместо переменных, и INDIRECT, который динамически собирает адреса ячеек из строк. Я смотрел на это и думал: чувак, ты же написал компилятор. Ты просто не знаешь об этом.
750 миллионов человек используют Excel. Для сравнения — на Python пишут примерно 15 миллионов, на JavaScript — около 17. Excel обгоняет их всех вместе взятых раз в двадцать. И вот что забавно: подавляющее большинство этих людей искренне считают, что они «просто работают с таблицами». Заполняют ячейки. Делают отчёты.
Нет, они программируют.
Формулы — это функции. Буквально.
Возьмём обычную формулу:
=СУММ(A1:A10) * (1 + B2)
Что здесь происходит? Вызов функции СУММ с аргументом-диапазоном, результат умножается на выражение в скобках. Никаких побочных эффектов, формула не меняет другие ячейки. При одинаковых входных данных всегда возвращает одинаковый результат. Композиция — результат одной функции подставляется в другую.
Это же чистые функции. Это же, простите, функциональное программирование.
И я не натягиваю сову на глобус. Саймон Пейтон-Джонс — один из создателей Haskell, если кто вдруг не в курсе — работал в Microsoft Research и прямо говорил, что Excel самый успешный функциональный язык в истории. Ну, справедливости ради, он ещё добавлял «к сожалению» — но это уже детали )
Подумайте: каждая ячейка — это привязка имени к выражению. B5 — это не «ячейка», это переменная. =A1+A2 — это не «формула», это определение функции без аргументов. Лист — пространство имён. Книга — модуль.
VLOOKUP — это hash table lookup
=ВПР(E2; A:B; 2; ЛОЖЬ)
Переведём на человеческий: «найди значение E2 в первом столбце диапазона A:B, верни соответствующее значение из второго столбца, точное совпадение». Это dict.get(key) в Python. Это map.find(key) в C++. Это lookup в хеш-таблице.
А ИНДЕКС + ПОИСКПОЗ? Это тот же lookup, но с разделённой адресацией — сначала находим позицию, потом по позиции достаём значение. Двухфазный поиск, как в базах данных с отдельным индексом.
Гипотетический бухгалтер Марина из соседнего отдела, которая «просто делает сводную табличку», на самом деле пишет запросы к структурам данных. Марина — программист. Марина об этом не знает, и лучше ей пока не говорить (она и так нервничает перед квартальным отчётом).
IF(AND(...)) — привет, pattern matching
=ЕСЛИ(И(A1>100; B1="Москва"); "VIP"; ЕСЛИ(A1>50; "Стандарт"; "Эконом"))
Вложенные ЕСЛИ — это switch/case. Или, если посмотреть с определённого ракурса, pattern matching. Не самый элегантный, конечно. Семь уровней вложенности ЕСЛИ — это то ещё зрелище, и я видел двенадцать.
Но ведь работает же.
А SWITCH, добавленный в Office 365:
=SWITCH(A1; 1;"Январь"; 2;"Февраль"; 3;"Март"; "Неизвестно")
Это уже просто нормальный switch-case, без вложенности. Даже с дефолтным значением.
IFS, MAXIFS, COUNTIFS — всё это фильтрация с предикатами. =СЧЁТЕСЛИ(A:A; ">100") — это filter(lambda x: x > 100, data).count(). Просто записано через ячейки вместо кода.
LAMBDA: момент, когда Excel перестал притворяться
В 2021 году Microsoft добавила LAMBDA в Excel. И вот тут всё стало совсем серьёзно.
=LAMBDA(x; y; x^2 + y^2)(3; 4)
Анонимная функция. Принимает два аргумента, возвращает сумму квадратов. Вызывается сразу с аргументами 3 и 4. Результат — 25.
Но это цветочки. LAMBDA можно присвоить имя через Диспетчер имён — и получить именованную функцию, которую можно вызывать из любой ячейки:
ГИПОТЕНУЗА = LAMBDA(a; b; КОРЕНЬ(a^2 + b^2))
Теперь =ГИПОТЕНУЗА(3; 4) возвращает 5. Пользовательская функция. Без VBA, без макросов, без единой строчки «настоящего» кода.
А ещё LAMBDA может вызывать сама себя. Рекурсия. В Excel.
ФАКТОРИАЛ = LAMBDA(n; ЕСЛИ(n<=1; 1; n * ФАКТОРИАЛ(n-1)))
Вместе с LAMBDA завезли MAP, REDUCE, SCAN, MAKEARRAY, BYROW, BYCOL. Это полноценные функции высшего порядка. MAP применяет лямбду к каждому элементу массива. REDUCE свёртывает массив в скаляр. Это буквально map и reduce из любого функционального языка, только в ячейках с рамочками.
Haskell-программисты сейчас либо плачут, либо обновляют резюме на «Senior Excel Developer».
Доказательство Тьюринг-полноты: Rule 110 в ячейках
Окей, но «похоже на программирование» и «Тьюринг-полон» — разные вещи. Можно ли на Excel вычислить всё, что вычислимо?
Можно. И это доказано.
Rule 110 — одномерный клеточный автомат, про который Мэтью Кук доказал Тьюринг-полноту в 2004 году. Правило простое: берём ячейку и двух её соседей (три бита → восемь комбинаций), для каждой комбинации определяем, будет ли ячейка живой в следующем поколении. «110» — это двоичное представление таблицы переходов: 01101110.
Реализация в Excel выглядит так (и это не шутка):
Строка 1 — начальное состояние. Одна ячейка = 1, остальн��е = 0.
Каждая последующая строка — новое поколение. Формула в ячейке B2:
=ЕСЛИ(ИЛИ( И(A1=1;B1=1;C1=1;0); И(A1=1;B1=1;C1=0;1); И(A1=1;B1=0;C1=1;1); И(A1=0;B1=1;C1=1;1); И(A1=0;B1=1;C1=0;1); И(A1=0;B1=0;C1=1;1); И(A1=0;B1=0;C1=0;0) ); 1; 0)
(Да, можно записать компактнее. Но так нагляднее.)
Копируем вправо и вниз. Включаем условное форматирование: 1 = чёрный, 0 = белый. И получаем характерный фрактальный треугольник Rule 110 — прямо в таблице.
Rule 110 — Тьюринг-полна. Excel реализует Rule 110. Следовательно, Excel — Тьюринг-полон.
Если вам кажется, что это слишком просто, то есть и другие подходы. Построение машины Тьюринга напрямую через ячейки (лента = строка, состояния = столбец, переходы через VLOOKUP). Реализация лямбда-исчисления через LAMBDA. Построение тега-систем. Все дороги ведут к одному: Excel вычисляет всё, что вычислимо.
(правда, он при этом может сожрать 16 гигабайт оперативки и зависнуть на полчаса, но это уже детали реализации)
Ужас из корпоративного мира
Знаете, что интересно? Не то, что Excel Тьюринг-полный язык. А то, что на этом Тьюринг-полном языке работает мировая финансовая система.
По разным оценкам, от 80% до 95% финансовых моделей в мире живут в .xlsx файлах. Инвестиционные банки. Хедж-фонды. Страховые компании. Центральные банки. Бюджеты государств. Всё это формулы в ячейках, без version control, без тестов, без code review.
И это ломается. Регулярно. Иногда эпически.
JPMorgan, 2012. Трейдер по прозвищу «Лондонский кит». Модель оценки рисков — Excel. Ошибка: в одной формуле вместо деления суммы на среднее стояло деление суммы на сумму. Copy-paste, забыли поправить. Результат — $6.2 миллиарда убытков. И��-за одной ячейки.
Расследование показало ещё кое-что: модель частично работала через ряд связанных Excel-файлов, и часть данных между ними передавалась copy-paste вручную. Вы представляете? Риск-модель банка с активами в $2.6 триллиона на copy-paste.
MI5, 2011. Британская контрразведка. Excel-таблица с телефонными номерами подозреваемых. Формат номера автоматически конвертировался — лишние цифры отбрасывались. Результат: прослушивали не тех людей.
Barclays, 2008. При покупке активов Lehman Brothers скрытые строки в Excel не были замечены при конвертации в PDF. Barclays случайно включил в сделку 179 контрактов, которые не собирался покупать.
И мой любимый жанр — «генетика vs. Excel». Десятки научных статей содержали ошибки, потому что Excel услужливо конвертировал названия генов в даты. SEPT2 (Septin 2) → 2-Sep. MARCH1 → 1-Mar. В 2020 году научное сообщество сдалось и переименовало 27 генов. Не Excel поправили, а гены переименовали. Видимо Excel победить невозможно.
Почему мы не относимся к этому серьёзно
Есть такой когнитивный фокус: мы не воспринимаем Excel как язык программирования, потому что у него нет атрибутов «настоящего» программирования. Нет текстового редактора с подсветкой синтаксиса (ну, формулы подсвечиваются, но это не считается, да?). Нет git. Нет Stack Overflow-тредов с пометкой [excel-lang].
А ещё — и это, кажется, главное — пользователи Excel не идентифицируют себя как программистов. Финансист не скажет «я пишу код». Он скажет «я строю модель». HR не скажет «я поддерживаю legacy-систему». Она скажет «я обновляю табличку с отпусками».
Но если мы применим формальные критерии:
Переменные? Ячейки.
Функции? Формулы. С LAMBDA — пользовательские функции с рекурсией.
Условная логика? IF, IFS, SWITCH.
Циклы? Ну, формально — через рекурсию в LAMBDA и через протягивание формул вниз (итерация по массиву).
Структуры данных? Таблицы, именованные диапазоны, массивы.
Ввод-вывод? Ячейки ввода, ячейки вывода, Power Query для чтения данных.
Тьюринг-полнота? Доказана.
Это язык программирования. Просто с очень необычным IDE.
(Кстати, хоть и необычным, но удивительно удобным для определённого класса задач. Мгновенная визуализация данных, zero deployment, отладка через тыканье в ячейки — попробуйте получить такой feedback loop в Python.)
Спагетти из ячеек
Каждый, кто наследовал чужой Excel-файл, знает это чувство. Открываешь, а там 47 листов. Формулы ссылаются на другие файлы, которых нет. Именованные диапазоны с именами типа xlnm.PrintArea. Циркулярные ссылки, которые «так и задумано». Условное форматирование на 200 правил. И где-то на листе «Лист3 (2) — копия» — та самая формула, от которой зависит весь квартальный отчёт.
Это же спагетти-код. Это буквально спагетти-код, только в ячейках. И самое грустное — к нему применимы все те же проблемы, от которых страдает обычный legacy: нет документации, автор уволился, никто не понимает почему оно работает, и все боятся что-то менять.
Только в обычном программировании мы хотя бы придумали инструменты: линтеры, тесты, CI/CD, code review. В Excel-мире этого (почти) нет. PwC делали исследование — 88% корпоративных таблиц содержат ошибки.
Мы бы ни за что не допустили такой уровень багов в продакшен-коде. Но в Excel — пожалуйста, вот ваш бюджет на 2026 год, в строке 847 формула ссылается не на тот столбец, удачи.
Что с этим делать
Можно, конечно, сказать «перепишите всё на Python». Ага. Скажите это финансовому директору, который 20 лет строит модели в Excel и чей мозг в буквальном смысле думает ячейками. Он вас вежливо пошлёт. И будет прав — его Excel-модель, при всех её проблемах, работает прямо сейчас, а ваш Python-скрипт надо ещё написать, протестировать, задокументировать, и убедить двадцать человек им пользоваться.
Microsoft, кажется, понимает ситуацию. LAMBDA и функции высшего порядка — это попытка дать Excel-программистам (да, программистам) более мощные инструменты, не заставляя их уходить из привычной среды. Power Query — это ETL прямо в Excel. Power Pivot — OLAP. Типы данных — это, по сути, структуры.
Может, правильный подход — не вытаскивать людей из Excel, а принести в Excel практики нормальной разработки? Тестирование, модульность?
А может, стоит просто признать очевидное. 750 миллионов людей пишут код каждый день. Они используют функциональный, Тьюринг-полный язык с графическим интерфейсом и мгновенным feedback loop. Этот язык запускает мировую финансовую систему, корпоративное планирование и половину научных исследований.
Но интересно, что самый массовый язык программирования в истории — тот, чьи пользователи не знают, что они программисты.
