-
-
Save kylefelipe/26cd5b8c883b1d4b446551e8ad63995a to your computer and use it in GitHub Desktop.
# -*- 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 |
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!
@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
Boa @FelipeSBarros, não tinha pensado nisso...
Eu criei um campo de mala direta chamado , mas não está substituindo. O que pode ser?
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
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.