Skip to content

Instantly share code, notes, and snippets.

@kylefelipe
Last active June 28, 2021 05:25
Show Gist options
  • Save kylefelipe/26cd5b8c883b1d4b446551e8ad63995a to your computer and use it in GitHub Desktop.
Save kylefelipe/26cd5b8c883b1d4b446551e8ad63995a to your computer and use it in GitHub Desktop.
Script python para gerar vários documentos usando um DOCX como template e uma planilha XLSX como base de dados
# -*- coding: utf-8 -*-
##################################################################################
# Script python para gerar vários documentos usando um DOCX como template
# e uma planilha XLSX como base de dados.
# é necessário ter um template preparado antes.
#
# Autor: Kyle Felipe Vieira Roberto
# Data de Criação: quarta-feira 19 de julho de 2017
#
##################################################################################
from docx import Document
from docx import table
from openpyxl import load_workbook
import re
# Códigos de auxílio
remover = "[-,./()]" # Remover caracteres
# Trabalhando os dados do EXCEL
# Abrindo o arquivo excel com a base de dados
caderno = load_workbook(filename='NOTIFICAR_TESTE.xlsx')
folhas = caderno['notificar'] # Escolhendo a aba com a base de dados
# Criando lista com CNPJs únicos
cnpj_unicos = set() # set pega apenas os dados únicos dos cnpjs
for linha in folhas.iter_rows('B{}:B{}' .format(folhas.min_row + 1, folhas.max_row)):
for celula in linha:
cnpj_unicos.add(celula.value)
lista_cnpj = list(cnpj_unicos) # Transformando o set em lista
# Dicionario com os nomes das empresas
cnpj_nome = {} # Chave referente aos dados dos cnpj
# Define a area de CNPJ e nomes
cnpj_nome_cel = folhas.iter_rows(('B{}:C{}' .format((folhas.min_row + 1), (folhas.max_row))))
# Popula o Dicionário cnpj_nome com os dados
for celula_1, celula_2 in cnpj_nome_cel:
cnpj_nome.update([('{}' .format(celula_1.value), '{}' .format(celula_2.value))])
total = len(cnpj_nome) # Pega o total de CNPJ de empresas a serem notificadas
# Solicitando alguns dados para as notificações
print('Quantidade de notificações: {}' .format(total))
data_notificação = input("Digite a data de notificação com o mês por extenso: ")
Notificacao_inicial = int(input('Qual a primeira notificação: ')) #Pega o número da primeira notificação
# Criando as notificações
for i in range(total):
documento = Document('NOTIFICA_Mala_direta.docx') # Abrindo o DOCX base da notificacao
cnpj = lista_cnpj[i]
cnp_limpo = (''.join(c for c in cnpj if c.isdigit())) # Limpa os caracteres especiais do CNPJ
nome_limpo = re.sub(remover, '', cnpj_nome[cnpj]) # Limpa os caracteres especiais do CNPJ retirar
num_notificacao = Notificacao_inicial + i # Cria o número da notificação
# cria uma lista com os paragrafos do texto, parágrafos necessários são 0, 3, 5, 6
para = list(documento.paragraphs)
# Modifica o texto do paragrafo 0 - numero da notificação
numnot_s = para[0].text
para[0].text = numnot_s.format(num_notificacao)
# Modifica o texto do parágrafo 3 - Data
empresa_s = para[3].text
para[3].text = empresa_s.format(data_notificação)
# Modifica o texto do parágrafo 5 - Empresa
empresa_s = para[5].text
para[5].text = empresa_s.format(re.sub(remover, '', cnpj_nome[cnpj]))
# Modifica o texto do parágrafo 6 - CNPJ
empresa_s = para[6].text
para[6].text = empresa_s.format(cnpj)
# Trabalhando os dados do EXCEL
dados_planilha = [] # Armazena os dados da empresa
# Define a área da planilha principal a ser usada
colunas_dados = folhas.iter_rows(
('B{}:J{}'.format((folhas.min_row + 1), (folhas.max_row)))) # Define a área dos valores da notificação
# Populando a lista aninhada com os dados da empresa (cnpj)
for cnpj_emp, empresa, codigo, produto, volume, medida, periodo, mes, ano in colunas_dados:
if cnpj_emp.value == cnpj:
dados_planilha.append([produto.value, volume.value, medida.value, mes.value, ano.value])
# Trabalhando a tabela da notificação
tabelas_d = list(documento.tables) # Pega a tabela criada dentro do documento padrão (template)
tabela_d = tabelas_d[0]
linhas_d = tabela_d.rows
cabeca_d = tabela_d.rows[0].cells # cabeçalho da tabela
# Polulando a tabela do documento
for item_d in dados_planilha:
adiciona = tabela_d.add_row().cells
adiciona[0].text = str(item_d[0])
adiciona[1].text = str(item_d[1])
adiciona[2].text = str(item_d[2])
adiciona[3].text = str(item_d[3])
adiciona[4].text = str(item_d[4])
# Mudando a formatação de cada célula da tabela do documento
for linha_d in tabela_d.rows:
for celula_d in linha_d.cells:
celula_d.paragraphs[0].style = documento.styles['Normal2'] # Pode criar um estilo dentro do documento
# do remplate q ser aplicado à célula da tabela
documento.save('NOTIFICAÇÃO nº {0} - {1}.docx'.format(num_notificacao,
nome_limpo)) # Salvando o arquivo
@isouzasoares
Copy link

Essas linhas,
58, 65 e 191 "leitura do documento", elas devem ser lidas somente uma vez, ou seja, acho que se ficar fora do for, ficará mais "leve", você está colentando os dados do doc padrão tratando e depois cuspindo um outro documento.

@FelipeSBarros
Copy link

Na linha 27 e 28 o file name 'NOTIFICAR_TESTE.xlsx' podería ser solicitado ao usuário, permitindo que a função seja utilizável idenpendente do nome do .xlsx.
Mas isso é só um ponto para que seja reproduzível de forma mais "livre"....
Good job!

@kylefelipe
Copy link
Author

@isouzasoares eu tentei usar fora do for, o problema é que na primeira iteração a variável {} era trocada e o texto do documento ficava o mesmo em todas as notificações... quando eu coloquei dentro funcionou do modo que eu queria

@kylefelipe
Copy link
Author

Boa @FelipeSBarros, não tinha pensado nisso...

@damiaorocha
Copy link

Eu criei um campo de mala direta chamado , mas não está substituindo. O que pode ser?

@kylefelipe
Copy link
Author

Eu criei um campo de mala direta chamado , mas não está substituindo. O que pode ser?
@damiaorocha
Raapz.. faz tanto tempo que fiz esse script....
Tem de ver o erro que está dando..
Se não me engano, quando fiz esse script. ele rodava em python 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment