Пишем формулы Excel
Снова удалось прочитать доклад в омской юзер-группе. Мне последнее время стало казаться, что “обычный” формат доклада с набором последовательных слайдов очень ограничен, поэтому в этот раз я попытался просто писать код и говорить. А в качестве примера я выбрал реализацию грида с формулами.
Как ни удивительно, но в моей практике было два случая, когда заказчики хотели “формулки, как в Экселе”. Правда, PMы всегда мужественно и непреклонно от этих хотелок отбивались. Но мне всегда мечталось попробовать такое написать. Вот и попробовал.
Конечно, написание более-менее законченного приложения для часового доклада – это чересчур. Поэтому я взял заготовку с уже работающим гридом, подготовленным для “прикручивания” к нему формул, и реально реализовывал только сам движок формул.
Чтобы было понятно, как оно выглядит, покажу:

По-правильному, надо было бы, наверное, писать какой-то парсер формул (с помощью, например, ANTLR), но этот путь казался слишком сложным. Поэтому я решил просто на лету генерировать класс, имеющий на каждую ячейку по публичному свойству (с говорящими именами A1, A2,…). Простые ячейки просто содержали единственный return значения, а ячейки с формулами – тупо возвращали текст формулы (например, “return A1+A2”, если формула была “=A1+A2”).
Этот класс я компилировал на лету с помощью CodeDomProvider, и общался с ним через Reflection. Очень просто и наглядно. Компиляция занимает порядка 0.1с, но необходима не всегда, если формулы не меняются, то обновлённые данные можно подсовывать также через Reflection.
Самое удивительное даже не то, что всё это работает, а то, что функционирующее ядро оказалось вполне возможно написать за 40 минут! Кому интересно, может скачать пример.
Использовать код из архива напрямую в продуктиве я настоятельно не рекомендую, так как и сам грид реализован весьма криво и вычислительное ядро забивает память кучей генерируемых сборок. Но для иллюстрации идеи – вполне.
Мне, конечно, была забавна сама идея динамической генерации кода. Раньше я такое встречал в интерпретаторах. По-моему, технология вполне применима на практике. Сгенерированный код работает быстро, так что можно переводить какие-то чужеродные структуры на язык C#. Например, компилировать нейронные сети. Или писать свой язык программирования.
На практике, конечно, наиболее логично применять динамическую компиляцию в каких-то инструментах для программистов. Например, в утилитах вроде LINQPad – самое место. А в целом хотелось донести мысль, что если давать волю фантазии, то можно свернуть горы. Ну или хотя бы разнообразить себе жизнь.