Huge formula in one column. How to have formula in a table and reference it in another table to avoid repeating it 1000s times?

I have a big formula creating a Risks Matrix.

If I have the risk matrix table with 150 records, it will repeat that big formula 150 times.

Is there a way to improve that, like having a table for formulas and referencing the formula you want in the Risk Table?

so each record instead of having a 14 thousand characters formula, will have a 100 characters formula retrieving the whole code from another table?

Hello @Rogerio_Penna
If i correctly understand you, then here is the solution:
https://docs.getgrist.com/wbxFDuErFHhe/RefFormulas?utm_id=share-doc

See here!

it is not working with my formula, maybe due to complexity, values being pulled from everywhere

def gerar_matriz_riscos():
    # Importações necessárias
    from datetime import datetime

    # Coletar todos os riscos
    todos_riscos = Riscos.all

    # Dicionários para armazenar os contadores e riscos por célula
    contagem_matriz = {}
    riscos_por_celula = {}

    # --- Adições Iniciadas ---
    planos_de_acoes = Planos_de_Acoes.all

    # Inicializa o conjunto para armazenar apenas IDs de riscos que têm planos de ação
    riscos_com_planos = set()

    # Extração de IDs numéricos de riscos vinculados a planos de ação
    for risco_fk in planos_de_acoes.RiscosFK:
        if risco_fk:  # Verifica se existe um valor válido
            riscos_com_planos.add(risco_fk.id)  # Adiciona o ID numérico ao conjunto

    # Debugging: Print all risks linked to action plans
    print("Planos de Ações - RiscosFK:")
    for risco_fk in planos_de_acoes.RiscosFK:
        print(f"- {risco_fk}")

    # Debugging: Print the set created
    print("Set of Risk IDs with Action Plans:")
    print(riscos_com_planos)

    data_atual = datetime.now().date()

    ultrapassados_por_celula = {}
    sem_planos_por_celula = {}

    # Variáveis para contagem de riscos totais e documentados (impacto/probabilidade zero)
    total_riscos = 0
    riscos_documentados = 0
    # --- Adições Finalizadas ---

    # Percorrer todos os riscos
    for risco in todos_riscos:
        # Obter a probabilidade e impacto atuais
        ultimo_impac = list(Analise_Risco.lookupRecords(RiscoFK=risco.id, sort_by="Data_Analise").ImpactNum)
        impacto_atual = ultimo_impac[-1] if ultimo_impac else risco.Impacto_Inerente_Num

        ultima_prob = list(Analise_Risco.lookupRecords(RiscoFK=risco.id, sort_by="Data_Analise").ProbNum)
        probabilidade_atual = ultima_prob[-1] if ultima_prob else risco.Probabilidade_Inerente_Num

        # Contagem de riscos totais
        total_riscos += 1

        # Contagem de riscos documentados (probabilidade ou impacto zero)
        if impacto_atual == 0 or probabilidade_atual == 0:
            riscos_documentados += 1
            continue  # Pula os riscos com impacto ou probabilidade zero

        # Índices inteiros para a matriz
        impacto_idx = int(impacto_atual)
        probabilidade_idx = int(probabilidade_atual)

        # Atualizar o contador na matriz
        chave = (probabilidade_idx, impacto_idx)
        contagem_matriz[chave] = contagem_matriz.get(chave, 0) + 1

        # Adicionar o risco à lista de riscos nessa célula
        riscos_por_celula.setdefault(chave, []).append(risco)

        # --- Adições Iniciadas ---
        if risco.id not in riscos_com_planos:
            sem_planos_por_celula[chave] = sem_planos_por_celula.get(chave, 0) + 1
        else:
            # Debugging: Print the risk ID that has an action plan
            print(f"Risk {risco.id} has an action plan.")

        analises = Analise_Risco.lookupRecords(RiscoFK=risco.id, sort_by="Data_Analise")
        if analises:
            ultima_analise = analises[-1]
            data_proxima = ultima_analise.Data_Proxima_Analise
            if data_proxima and data_proxima < data_atual:
                ultrapassados_por_celula[chave] = ultrapassados_por_celula.get(chave, 0) + 1
        # --- Adições Finalizadas ---

    def obter_cor_risco(risk_score):
        if risk_score == 0:
            return ('#d3d3d3', 'Inexistente')
        elif risk_score <= 2:
            return ('#157AFB', 'Muito Baixo')
        elif risk_score <= 5:
            return ('#2AE028', 'Baixo')
        elif risk_score <= 10:
            return ('#E8D62F', 'Moderado')
        elif risk_score <= 16:
            return ('#FD9D28', 'Elevado')
        else:
            return ('#E00A17', 'Extremo')

    risco_selecionado = rec

    ultimo_impac_sel = list(Analise_Risco.lookupRecords(RiscoFK=risco_selecionado.id, sort_by="Data_Analise").ImpactNum)
    impacto_atual_sel = ultimo_impac_sel[-1] if ultimo_impac_sel else risco_selecionado.Impacto_Inerente_Num

    ultima_prob_sel = list(Analise_Risco.lookupRecords(RiscoFK=risco_selecionado.id, sort_by="Data_Analise").ProbNum)
    probabilidade_atual_sel = ultima_prob_sel[-1] if ultima_prob_sel else risco_selecionado.Probabilidade_Inerente_Num

    impacto_idx_sel = int(impacto_atual_sel)
    probabilidade_idx_sel = int(probabilidade_atual_sel)
    chave_selecionada = (probabilidade_idx_sel, impacto_idx_sel)

    max_valor = 5

    html = '<table style="border-collapse: separate; border-spacing: 2px; width: 100%; height: 100%; table-layout: fixed;">'

    # Mesclar as células 2x2 no topo e exibir contagens
    html += f'''
    <tr>
        <th rowspan="2" colspan="2" style="background-color: #4f4f4f; width: 80px; height: 100px; border: 1px solid white; border-radius: 8px; box-shadow: inset 0 0 0 2px #3d3d3d; color: white; text-align: center; vertical-align: middle;">
            <div>⚠️ {total_riscos}</div>
            <div>📄 {riscos_documentados}</div>
        </th>
        <th colspan="5" style="background-color: #4f4f4f; color: white; text-align: center; border: 1px solid white; border-radius: 8px; box-shadow: inset 0 0 0 2px #3d3d3d;">IMPACTO</th>
    </tr>
    '''

    html += '<tr>'
    for prob in range(1, max_valor + 1):
        html += f'<th style="background-color: #4f4f4f; color: white; text-align: center; width: 80px; border: 1px solid white; border-radius: 8px; box-shadow: inset 0 0 0 2px #3d3d3d;">{prob}</th>'
    html += '</tr>'

    for i in range(max_valor, 0, -1):
        if i == max_valor:
            html += '<tr>'
            html += '<th rowspan="5" style="background-color: #4f4f4f; color: white; text-align: center; vertical-align: middle; writing-mode: vertical-rl; transform: rotate(180deg); border: 1px solid white; border-radius: 8px; box-shadow: inset 0 0 0 2px #3d3d3d;">PROBABILIDADE</th>'
        html += f'<th style="background-color: #4f4f4f; color: white; text-align: center; width: 40px; border: 1px solid white; border-radius: 8px; box-shadow: inset 0 0 0 2px #3d3d3d;">{i}</th>'

        for prob in range(1, max_valor + 1):
            chave = (prob, i)
            count = contagem_matriz.get(chave, 0)
            risk_score = prob * i
            cor_celula, nivel_risco = obter_cor_risco(risk_score)

            def escurecer_cor(cor):
                cor_rgb = tuple(int(cor.lstrip('#')[j:j+2], 16) for j in (0, 2, 4))
                cor_rgb_escura = tuple(max(int(c * 0.8), 0) for c in cor_rgb)
                return f'rgb{cor_rgb_escura}'

            cor_borda = escurecer_cor(cor_celula)

            is_selected_cell = (prob, i) == chave_selecionada

            cell_style = f'background-color: {cor_celula}; border-radius: 8px; box-shadow: inset 0 0 0 2px {cor_borda}; border: 1px solid white; position: relative; height: 50px;'
            if is_selected_cell:
                cell_style += ' outline: 3px solid black;'

            riscos_na_celula = riscos_por_celula.get(chave, [])
            if riscos_na_celula:
                tooltip_lines = [f"Riscos nesta célula:"]
                for r in riscos_na_celula:
                    tooltip_lines.append(f"ID: {r.id}, Nome: {r.NomeRisco}")
                tooltip_text = '&#013;'.join(tooltip_lines)
            else:
                tooltip_text = "Nenhum risco nesta célula"

            tooltip_text = tooltip_text.replace('"', '&quot;')

            sem_planos = sem_planos_por_celula.get(chave, 0)
            ultrapassados = ultrapassados_por_celula.get(chave, 0)

            html += f'<td style="{cell_style}" title="{tooltip_text}">'
            html += f'<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">'

            if count > 0:
                html += f'<div style="background-color: rgba(255, 255, 255, 0.75); border: 2px solid #333; border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 16px;">{count}</div>'
            else:
                html += '&nbsp;'
            html += '</div>'

            if sem_planos > 0:
                html += f'''
                <div style="
                    position: absolute;
                    top: 2px;
                    right: 2px;
                    background-color: #FF0000;
                    color: white;
                    font-size: 10px;
                    padding: 2px 4px;
                    border-radius: 50%;
                    pointer-events: none;
                    border: 1px solid black;">
                    {sem_planos}
                </div>
                '''

            if ultrapassados > 0:
                html += f'''
                <div style="
                    position: absolute;
                    bottom: 2px;
                    right: 2px;
                    background-color: #FFA500;
                    color: white;
                    font-size: 10px;
                    padding: 2px 4px;
                    border-radius: 50%;
                    pointer-events: none;
                    border: 1px solid black;">
                    {ultrapassados}
                </div>
                '''
            html += '</td>'
        html += '</tr>'

    html += '</table>'

    # Botão Legenda com Tooltip
    html += '''
    <div style="margin-top: 10px; display: inline-block;">
        <button style="padding: 5px 10px; border: none; background-color: #4f4f4f; color: white; border-radius: 5px; cursor: pointer;" title="Registro de Riscos
⚠️ Total de Riscos
📄 Somente Documentados
Células da Matriz
⚪ Riscos na célula
🔴 Riscos sem planos de ação
🟠 Riscos com prazo ultrapassado
Graus de Risco
🟦 Muito Baixo
🟩 Baixo
🟨 Moderado
🟧 Elevado
🟥 Extremo">
            Legenda
        </button>
    </div>
    '''

    return html

return gerar_matriz_riscos()

it should result in this
image

  1. when you added the custom code to the cell, did you enter it as a formula? It looks like from your screenshot that it’s just text

  2. where are you attempting to call the user code from?

  3. why are you using eval(), and where is that function that you’re passing in?

I used the eval() and formula as text per Bibo’s suggestion

that’s why that specific reply was to him. It works with simpler formulas however. Like in the example in his link

I had already made it work with one of the Risk Matrix

see, very small code in the column

referencing this formula at another table

HOWEVER

this other Risk Matrix (for individual selected risks, showing the evolution of the risk according to Risk Analysis)
image

I had to put directly in the main RIsks table

if I put that formula in another table I get an attribute error
image

image

Probably because THIS formula tries to access the currently selected record in the Risks table, but the formula is being executed from the context of that other table only for formulas.

btw, in my “formulas table”, I created four columns for testing.

two columns for each Risk Matrix formula. One column as formula, another as text. Then tried both methods with each code.