[Python] Substituição de tags em templates docx utilizando Python [fechada]

Discussão em 'Python' iniciado por Stack, Outubro 30, 2024.

  1. Stack

    Stack Membro Participativo

    Estou com um probleminha em python. Tenho um código que tem a função de substituir tags em documentos docx, no template original as tags seguem uma formatação padrão, quando o código é executado o texto que substitui as tags perde a formatação, dito isso encontrei uma solução, porém não foi 100% efetiva, a função esta realizando a formatação das tags mas não está respeitando a regra para deixar algumas delas em negrito, qual será o problema? Lembrando que essas tags podem se repetir em varias partes do template.

    Esse é o código:

    # -*- coding: utf-8 -*-
    import pyodbc
    from docx import Document
    from docx.shared import Pt
    from docx.oxml.ns import qn
    import os
    import time
    import logging

    # Configuração do logger
    log_file_path = 'TemplatesJuridico/log/script_log.log'
    logging.basicConfig(
    filename=log_file_path,
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
    )

    # Função para substituir tags e aplicar formatação específica
    def substituir_em_runs(paragraph, tag, valor):
    tag_formatacao = {
    '<nr_contrato_cliente>': {'font_name': 'Calibri', 'font_size': 12, 'bold': True},
    '<ano_corrente>': {'font_name': 'Calibri', 'font_size': 12, 'bold': True},
    '<nome_cliente>': {'font_name': 'Calibri', 'font_size': 10, 'bold': True},
    '<nome_parceiro>': {'font_name': 'Calibri', 'font_size': 10, 'bold': True},
    '<nome_indice_reajuste>': {'font_name': 'Calibri', 'font_size': 10, 'bold': False},
    '<nr_mes_reajuste>': {'font_name': 'Calibri', 'font_size': 10, 'bold': False},
    }
    default_formatacao = {'font_name': 'Calibri', 'font_size': 10, 'bold': False}

    # Verifica se a tag está presente no parágrafo
    full_text = ''.join(run.text for run in paragraph.runs)
    if tag not in full_text:
    return

    # Substitui a tag pelo valor
    novo_texto = full_text.replace(tag, valor if valor else "")
    for run in paragraph.runs:
    run.text = ""

    # Determina a formatação correta para a tag
    formatacao = tag_formatacao.get(tag, default_formatacao)

    # Adiciona o novo texto no parágrafo com formatação
    new_run = paragraph.add_run(novo_texto)
    new_run.font.name = formatacao['font_name']
    new_run.font.size = Pt(formatacao['font_size'])
    new_run.font.bold = formatacao['bold']
    r = new_run._element
    r.rPr.rFonts.set(qn('w:eastAsia'), formatacao['font_name'])

    # Função principal para substituir tags no documento
    def substituir_tags(doc, tags_mapping):
    for paragraph in doc.paragraphs:
    for tag, valor in tags_mapping.items():
    substituir_em_runs(paragraph, tag, valor)

    for table in doc.tables:
    for row in table.rows:
    for cell in row.cells:
    for paragraph in cell.paragraphs:
    for tag, valor in tags_mapping.items():
    substituir_em_runs(paragraph, tag, valor)

    # Função para gerar o template
    def gerar_template(numcontrato, opcao):
    if hasattr(gerar_template, "execuuted"):
    logging.info(f"Processo para o contrato {numcontrato} ja foi executado.")
    return
    gerar_template.executed = True

    start_time = time.time()

    try:
    logging.debug("Tentando conectar ao banco de dados.")
    conn = pyodbc.connect(connection_string)
    cursor = conn.cursor()
    logging.info("Conexao com o banco de dados estabelecida com sucesso.")
    except pyodbc.Error as e:
    logging.error(f"Erro ao conectar ao banco de dados: {e}")
    return

    # Aqui esta a query que busca aas informações do banco

    try:
    logging.debug(f"Executando a query: {query} com o parametro {numcontrato}")
    cursor.execute(query, numcontrato)
    resultado = cursor.fetchone()
    logging.debug(f"Resultado da consulta: {resultado}")
    except pyodbc.Error as e:
    logging.error(f"Erro ao executar a query SQL: {e}")
    return

    if resultado:
    try:
    (nr_contrato_cliente, nome_cliente, nome_parceiro, valor_contrato, data_contrato, descricao_servico,
    cidade_cliente, cidade_parceiro, uf_cidade_cliente, uf_cidade_parceiro, cep_cliente,
    cnpj_cliente, cnpj_parceiro, ie_cliente, end_cliente, end_parceiro, nr_cliente,
    nr_parceiro, bairro_cliente, ano_corrente, nome_indice_reajuste, mes_reajuste, nr_mes_reajuste) = resultado
    except ValueError as e:
    logging.error(f"Erro ao desempacotar o resultado: {e}")
    return
    else:
    logging.warning(f'Nenhum dado encontrado para o contrato {numcontrato}.')
    return

    cursor.close()
    conn.close()
    logging.info(f"Conexao com o banco de dados encerrada para o contrato {numcontrato}.")

    # Definir o caminho do template e o nome do arquivo de saída

    # Evita sobreescrever o arquivo
    counter = 1
    while os.path.exists(output_path):
    output_path = f"{base_output_path}_{counter}.docx"
    counter += 1

    doc = Document(template_path)

    tags_mapping = {
    '<nr_contrato_cliente>': str(nr_contrato_cliente or ""),
    '<nome_cliente>': nome_cliente or "",
    '<nome_parceiro>': nome_parceiro or "",
    '<valor_contrato>': f"{valor_contrato:,.2f}" if valor_contrato is not None else "",
    '<data_contrato>': data_contrato or "",
    '<DESCRICAO_SERVICO>': descricao_servico or "",
    '<cidade_cliente>': cidade_cliente or "",
    '<cidade_parceiro>': cidade_parceiro or "",
    '<uf_cidade_cliente>': uf_cidade_cliente or "",
    '<uf_cidade_parceiro>': uf_cidade_parceiro or "",
    '<cep_cliente>': cep_cliente or "",
    '<cnpj_cliente>': cnpj_cliente or "",
    '<cnpj_parceiro>': cnpj_parceiro or "",
    '<ie_cliente>': ie_cliente or "",
    '<end_cliente>': end_cliente or "",
    '<end_parceiro>': end_parceiro or "",
    '<nr_cliente>': str(nr_cliente or ""),
    '<nr_parceiro>': str(nr_parceiro or ""),
    '<bairro_cliente>': bairro_cliente or "",
    '<ano_corrente>': str(ano_corrente or ""),
    '<nome_indice_reajuste>': nome_indice_reajuste or "",
    '<mes_reajuste>': mes_reajuste or "",
    '<nr_mes_reajuste>': nr_mes_reajuste or ""
    }

    substituir_tags(doc, tags_mapping)
    doc.save(output_path)
    logging.info(f"Template gerado com sucesso: {output_path}")

    end_time = time.time()
    elapsed_time = end_time - start_time
    logging.info(f"Template gerado com sucesso para o contrato {numcontrato}. Tempo total de execucao: {elapsed_time:.2f} segundos.")


    Desde já agradeço a ajuda.

    Eu tento formatar as tags conforme o código, mas não esta sendo 100% funcional, o problema está em deixar o texto substituído em negrito.

    Já fiz varias pesquisas e não encontrei a solução.

    Continue reading...

Compartilhe esta Página