承接 sobolevwladimir/vexcel 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sobolevwladimir/vexcel

Composer 安装命令:

composer require sobolevwladimir/vexcel

包简介

Parse excel formula to syntax tree

README 文档

README

vexcel

Позволяет использовать формулы excel в вашем приложении.

Описание:

Формулы в эксель - это прекрасное изобретение,которое позволяет пользователям производить рассчеты без (помощи) программистов. Нередко возникают ситуации, когда такой функционал нужен в вашем приложении! Эта библиотека позволит вам использовать выражения, синтаксически похожие на формулы из excel, с той лишь разницей, что вместо координат ячеек вы сможете использовать свои переменные.

Демо

http://vexcel.vladimir-sobolev.ru

Особенности:

  • Excel подобный синтаксис.
  • Поддержка переменных, задаваемых извне.
  • Математический порядок действий (Пример: 2+2*3 получим 8).
  • Поддерживает функции (ЕСЛИ, НЕ, ОКРУГЛИТЬ и т.д.).
  • Возможность добавлять свои функции.
  • Преобразование синтаксического дерева в json и обратно.
  • Хранение переменных в синтаксическом дереве в виде идентификаторов.
  • Возможность преобразовать синтаксическое дерево обратно в формулу. (Полезно, если возможно изменение названий переменных со временем).

Синтаксис

Строка

Начинается и заканчивается одинарными или двойными кавычками. Пример: "моя строка", 'моя строка'

Число

Число бывает двух видов: Обычное и дробное. Дробные числа пишутся через точку.

Пример целого числа: 1200

Пример дробного числа: 3.2

Переменная

Название переменной должно начинаться с буквы и может содержать в своем названии буквы, цифры и нижнее подчеркивание. Пример: Вася, Моя_ПЕР

Переменные также могут включать любые символы включая пробел, если название переменной обернуто в '$' или ''. Пример: $Моя ПЕР$, *\Моя ПЕР*

Функция

Название переменной должно начинаться с буквы и может содержать в своем названии буквы, цифры и нижнее подчеркивание. В конце названия функции идет круглая скобка, после которой передаются аргументы этой функции, разделенные знаком: точка с запятой. Функция заканчивается после закрывающей скобки. Пример: МОЯ_ФУНКЦИЯ(ПЕР1; ПЕР2)

Установка

composer require sobolevwladimir/vexcel

Начало работы

Подключение:

<?php
...
use SobolevWladimir\Vexcel\Parser\Parser;

Далее нам можно преобразовать нашу формулу в абстрактное синтаксическое дерево (Далее АСТ).

$parser = new Parser();
$ast = $parser->parse('3+3');// Получили синтаксическое дерево

Для получения значения вызовем функцию calculate():

$answer = $ast->calculate(); // $answer = 6

Почему тут столько шагов? Т.к сам расчет производится в АСТ, вам достаточно один раз распарсить формулу, а потом, меняя на ходу значения переменных, рассчитать значение уже для нового поля (про переменные ниже ). Например:

$parser = new Parser();
$ast = $parser->parse('ВАША_ПЕРЕМЕННАЯ+3');// Получили синтаксическое дерево

foreach($repositorys as $repository) {
    $answer = $ast->calculate($repository);
    // ... you code
}

Использование переменных в формулах:

Для использования переменных, нам необходимо объяснить системе: откуда брать значения переменных. Для этого создайте класс, реализующий интерфейс ValueRepository. Например, давайте представим, что у нас есть переменные, названия которых соответствуют числам ("ПЕРЕМЕН_ОДИН"=1, "ПЕРЕМЕН_ДВА"=2, "ПЕРЕМЕН_ТРИ"=3 и тд). Тогда класс будет иметь следующий вид:

use SobolevWladimir\Vexcel\Repository\ValueRepositoryInterface;

class ValueRepositoryFake implements ValueRepositoryInterface
{
    /** @var array<string, int> */
    private array $variables = [
        'ПЕРЕМЕН_ОДИН'   => 1,
        'ПЕРЕМЕН_ДВА'    => 2,
        'ПЕРЕМЕН_ТРИ'    => 3,
        'ПЕРЕМЕН_ЧЕТЫРЕ' => 4,
        'ПЕРЕМЕН_ПЯТЬ'   => 5,
        'ПЕРЕМЕН_ШЕСТЬ'  => 6,
    ];

    public function getValueByIdentifier(string $identificator): mixed
    {
        return $this->variables[$identificator];
    }

   
}

Функция getValueByIdentifier принимает идентификатор переменной (по умолчанию идентификатор равен имени переменной. cм. подробнее: хранение формул в БД ) и возращает значение.

Далее мы передаем экземпляр этого класса для подсчета:

$parser = new Parser();
$ast = $parser->parse('ПЕРЕМЕН_ТРИ+3');// Получили синтаксическое дерево

$repository = new ValueRepositoryFake();// Наш репозиторий

$answer = $ast->calculate($repository); // $answer = 6

Использование функций:

$parser = new Parser();
$ast = $parser->parse('ЕСЛИ(НЕ(3<2);"ДА";"НЕТ")');// Получили синтаксическое дерево
$answer = $ast->calculate(); // $answer = 'ДА'

На данный момент реализованы следующие функции по умолчанию: 'ЕСЛИ', 'НЕ', 'ОКРУГЛВЕРХ', 'ОКРУГЛНИЗ'. Если вам необходимо реализовать свои функции, то создайте класс, унаследованный от FunctionBuilder и переопределите метод "build":

$parser = new Parser(functionBuilder: new YouFunctionBuilder());
$ast = $parser->parse('МОЯФУНЦИЯ(3<2)');// Получили синтаксическое дерево
$answer = $ast->calculate(); 

Хранение формул в БД

Если в вашей формуле есть переменные, название которых могут менятся со временем (Как пример: ваши переменные хранятся в БД), то имеет смысл хранить не саму формулу, введеную пользователем, а АСТ, и в нем хранить постоянные идентификаторы на эти переменные. Тогда при преобразовании дерева обратно в формулу названия переменных будет востановленно по идентификаторам.

Для этого:

  1. Создайте класс, реализующий интерфейс VariableRepositoryInterface и передайте его в конструктор Parser().
  2. Преобразуйте формулу в АСТ путем вызова $parser->parse();
  3. Это дерево сохраните в виде json в бд (json_encode($ast)).

Чтобы преобразовать json обратно в синтаксическое дерево, выполните следующую процедуру:

$ast = FormulaAST::fromJson(json_decode((string)$formulaJson, true)); 

Далее можно преобразовать это дерево обратно в формулу:

$encoder = new VexcelEncoder($youVariableRepository); 
$code = $ast->toCode($encoder); 

sobolevwladimir/vexcel 适用场景与选型建议

sobolevwladimir/vexcel 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 8.82k 次下载、GitHub Stars 达 7, 最近一次更新时间为 2023 年 08 月 24 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「excel」 「parser」 「syntax」 「formula」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 sobolevwladimir/vexcel 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 sobolevwladimir/vexcel 我们能提供哪些服务?
定制开发 / 二次开发

基于 sobolevwladimir/vexcel 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 8.82k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 8
  • 点击次数: 12
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 7
  • Watchers: 2
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-08-24