# FormulaParser.java

    package cloud.wconnect.finance.service.pl.parseLayout;

    import cloud.wconnect.finance.pojo.dto.pl.LayoutElement;

    import java.util.ArrayList;
    import java.util.List;

    /**
     * 解析公式
     */
    public class FormulaParser {

        /**
         * 解析公式
         *
         * @param elements 表格元素
         * @return void
         * @author lichen
         * @date 2025/9/25
         */
        public static void parse(List<LayoutElement> elements) {
            int groupStartIdx = -1;
            List<LayoutElement> elementStack = new ArrayList<>();
            for (int i = 0, Max = elements.size(); i < Max; i++) {
                LayoutElement ele = elements.get(i);

                if (ele.getOption() != null && !ele.getOption().isEmpty() && ele.getOption().contains("Group Start.")) {
                    groupStartIdx = i;
                    elementStack.clear();
                }

                if ("Item".equals(ele.getType())) {
                    // nothing to do
                } else if ("Formula".equals(ele.getType())) {

                    if (ele.getFormula() != null && !ele.getFormula().isEmpty()) {
                        ele.setFormula(ele.getFormula().replaceAll("\\{[^}]*?(\\d+)\\s*:\\s*(\\d+).*?}", "{$1:$2}"));
                    }

                } else if ("Item Sub-Total".equals(ele.getType())) {

                    StringBuilder formulaBuilder = new StringBuilder();
                    List<LayoutElement> elementsToRemove = new ArrayList<>();

                    for (LayoutElement stackEle : elementStack) {
                        if ("Formula".equals(stackEle.getType()) || "Item".equals(stackEle.getType())) {
                            if (!formulaBuilder.isEmpty()) {
                                formulaBuilder.append(" + ");
                            }
                            formulaBuilder.append("{").append(stackEle.getRowId()).append("}");

                            elementsToRemove.add(stackEle);
                        }
                    }

                    if (!formulaBuilder.isEmpty()) {
                        ele.setFormula(formulaBuilder.toString());
                    }

                    elementStack.removeAll(elementsToRemove);

                } else if ("Group Sub-Total".equals(ele.getType())) {

                    StringBuilder formulaBuilder = new StringBuilder();

                    for (LayoutElement stackEle : elementStack) {
                        if ("Formula".equals(stackEle.getType()) || "Item".equals(stackEle.getType())
                                || "Item Sub-Total".equals(stackEle.getType())
                                || "Group Sub-Total".equals(stackEle.getType())) {

                            if (!formulaBuilder.isEmpty()) {
                                formulaBuilder.append(" + ");
                            }
                            formulaBuilder.append("{").append(stackEle.getRowId()).append("}");
                        }
                    }

                    if (!formulaBuilder.isEmpty()) {
                        ele.setFormula(formulaBuilder.toString());
                    }

                    elementStack.clear();

                } else {
                    continue;
                }

                if (groupStartIdx > -1) {
                    elementStack.add(ele);
                }
            }
        }
    }