Created
June 3, 2018 23:59
-
-
Save ndvo/366184bbf4d4916e8b822d07bb669669 to your computer and use it in GitHub Desktop.
Preparador de arquivos csv para mapas estáticos do SIMPR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import xlrd #leitor de arquivos em excel | |
import csv #lidar com arquivos em csv | |
import os # lidar com o sistema operacional (pastas e arquivos) | |
import sys # lidar com diferentes sistemas operacionais (linux e windows) | |
import codecs # lidar com difirentes codificações de caracteres | |
import cStringIO | |
from Tkinter import * # Criar janelas e interfaces gráficas | |
import tkSimpleDialog | |
import tkMessageBox | |
import Tkconstants | |
import tkFileDialog | |
coluna_cod_mun = 2 | |
coluna_info = 4 | |
coluna_nome = 9 | |
class UnicodeWriter: | |
""" | |
A CSV writer which will write rows to CSV file "f", | |
which is encoded in the given encoding. | |
""" | |
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): | |
# Redirect output to a queue | |
self.queue = cStringIO.StringIO() | |
self.writer = csv.writer(self.queue, dialect=dialect, **kwds) | |
self.stream = f | |
self.encoder = codecs.getincrementalencoder(encoding)() | |
def writerow(self, row): | |
self.writer.writerow([unicode(s).encode("utf-8") for s in row]) | |
# Fetch UTF-8 output from the queue ... | |
data = self.queue.getvalue() | |
data = data.decode("utf-8") | |
# ... and reencode it into the target encoding | |
data = self.encoder.encode(data) | |
# write to the target stream | |
self.stream.write(data) | |
# empty queue | |
self.queue.truncate(0) | |
def writerows(self, rows): | |
for row in rows: | |
self.writerow(row) | |
def unicode_csv_reader(utf8_data, dialect=csv.excel, **kwargs): | |
csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs) | |
for row in csv_reader: | |
yield [unicode(cell, 'utf-8') for cell in row] | |
class Regiao(): | |
def __init__(self, nome, codigo): | |
self.nome = nome | |
self.codigo = codigo | |
self.itens = {} | |
self.empreendimentos = [] | |
self.totais = {} | |
class StatusBar(Frame): | |
def __init__(self, root): | |
Frame.__init__(self, root) | |
self.label = Label(self, bd=1, relief=SUNKEN, anchor=W) | |
self.label.pack(fill=X) | |
def set(self, format, *args): | |
self.label.config(text=format % args) | |
self.label.update_idletasks() | |
def clear(self): | |
self.label.config(text="") | |
self.label.update_idletasks() | |
class App(): | |
def __init__(self, root): | |
self.source_file = None | |
self.operacoes_disponiveis = ['Ocultar','soma', 'max','min'] | |
self.cabecalho = [] | |
self.operacao_selecionada = {} | |
self.dados_municipais_padrao = os.path.join(os.path.expanduser('~'),'dados_municipais.csv') | |
self.dados_municipais = None | |
frame = Frame(root,width=200, height=100) | |
self.frame = frame | |
namelbl = Label(frame, text=u"Agregador para construção de mapas SIM-PR") | |
name = Entry(frame) | |
# create a menu | |
menu = Menu(root) | |
root.config(menu=menu) | |
filemenu = Menu(menu) | |
menu.add_cascade(label="Arquivo", menu=filemenu) | |
filemenu.add_command(label="Fonte de Dados Municipais", command=self.open_dados_municipais) | |
filemenu.add_command(label="Arquivo com os dados a trabalhar", command=self.open_dados_a_trabalhar) | |
filemenu.add_separator() | |
filemenu.add_command(label="Sair", command=callback) | |
settingsmenu = Menu(menu) | |
menu.add_cascade(label=u"Configurações",menu=settingsmenu) | |
settingsmenu.add_command(label=u"Definir Coluna do Código do Município", command=self.set_coluna_codmun) | |
helpmenu = Menu(menu) | |
menu.add_cascade(label="Ajuda", menu=helpmenu) | |
helpmenu.add_command(label="Como Usar", command=self.help) | |
helpmenu.add_command(label="Sobre", command=self.about) | |
#Prepara a caixa de texto do log | |
self.text_scroll=Scrollbar(frame, orient=VERTICAL) | |
self.text=Text(frame,height=40,width=80,background='white',yscrollcommand=self.text_scroll.set) | |
self.text_scroll.config(command=self.text.yview) | |
self.text.tag_config("blue_white", foreground="blue",background="white") | |
self.print_initial_message() | |
self.button_sair = Button(frame, text="Sair", fg="red", command=frame.quit) | |
self.button_executar = Button(frame, text="Executar", fg="black", command=self.aplicar_script) | |
self.button_agregar = Button(frame, text="Agregar", fg="black", command=self.agregar_por_regioes) | |
listrotulo = Label(frame, text="Selecione a coluna") | |
self.listbox_scrollbar = Scrollbar(frame, orient=VERTICAL) | |
self.listbox = Listbox(frame, yscrollcommand=self.listbox_scrollbar.set, exportselection = 0) | |
self.listbox_scrollbar.config(command=self.listbox.yview) | |
self.listbox.bind('<<ListboxSelect>>', self.action_listbox) | |
operacaorotulo = Label(frame, text=u"Selecione as operações\n para cada nível de agregação") | |
operacao_pais_rotulo = Label(frame, text=u"País") | |
self.operacao_pais_listbox = Listbox(frame, exportselection=0,height=3) | |
self.operacao_pais_listbox.bind('<<ListboxSelect>>', self.action_operacao_listbox) | |
operacao_regiao_rotulo = Label(frame, text=u"Região") | |
self.operacao_regiao_listbox = Listbox(frame, exportselection=0,height=3) | |
self.operacao_regiao_listbox.bind('<<ListboxSelect>>', self.action_operacao_listbox) | |
operacao_estado_rotulo = Label(frame, text=u"Estado") | |
self.operacao_estado_listbox = Listbox(frame, exportselection=0,height=3) | |
self.operacao_estado_listbox.bind('<<ListboxSelect>>', self.action_operacao_listbox) | |
operacao_municipio_rotulo = Label(frame, text=u"Município") | |
self.operacao_municipio_listbox = Listbox(frame, exportselection=0,height=3) | |
self.operacao_municipio_listbox.bind('<<ListboxSelect>>', self.action_operacao_listbox) | |
self.niveis_operacoes = [ | |
self.operacao_pais_listbox, | |
self.operacao_regiao_listbox, | |
self.operacao_estado_listbox, | |
self.operacao_municipio_listbox, | |
] | |
agregada_rotulo = Label(frame, text=u'Colunas a Agregar\n Por região na Tabela') | |
self.agregada_scroll = Scrollbar(frame, orient=VERTICAL) | |
self.agregada_text = Text(frame,height=10, width=25,background="#d9d9d9") | |
self.agregada_scroll.config(command=self.agregada_text.yview) | |
#### Posiciona os widgets na tela ### | |
frame.grid(column=0, row=0, columnspan=10, rowspan=6) | |
namelbl.grid(column=1, row=0) | |
self.text.grid(column=1,row=1, columnspan=3,rowspan=14, sticky=N+S) | |
self.text_scroll.grid(column=5, row=1, rowspan=14,sticky=N+S) | |
listrotulo.grid(column=6, row=0) | |
self.listbox.grid(column=6, row=1, sticky=N+S) | |
self.listbox_scrollbar.grid(column=7, row=1, sticky=N+S) | |
operacaorotulo.grid(column=6, row=2, sticky = S) | |
operacao_pais_rotulo.grid(column=6, row=3, sticky = S) | |
self.operacao_pais_listbox.grid(column = 6, row = 4, sticky=N) | |
operacao_regiao_rotulo.grid(column=6, row=5, sticky = S) | |
self.operacao_regiao_listbox.grid(column = 6, row = 6, sticky=N) | |
operacao_estado_rotulo.grid(column=6, row=7, sticky = S) | |
self.operacao_estado_listbox.grid(column = 6, row = 8, sticky=N) | |
operacao_municipio_rotulo.grid(column=6, row=9, sticky = S) | |
self.operacao_municipio_listbox.grid(column = 6, row = 10, sticky=N) | |
agregada_rotulo.grid(column=6, row=11, sticky=S) | |
self.agregada_text.grid(column=6,row=12,sticky=N, columnspan=1) | |
self.agregada_text.config(state=DISABLED) | |
self.button_sair.grid(column=1, row=15) | |
self.button_executar.grid(column=2, row=15) | |
self.button_agregar.grid(column=3, row=15) | |
#Informa o usuário que não há ainda um arquivo selecionado | |
self.listbox.insert(END, u"Não há arquivo selecionado.") | |
self.status = StatusBar(root) | |
self.status.grid(column=0,row=10,columnspan=10,sticky=E+W) | |
self.status.set('Nenhuma planilha selecionada.') | |
self.resultados = None | |
def set_coluna_codmun(self): | |
nova_coluna = tkSimpleDialog.askinteger('Que coluna contém o código do município?', 'Digite o número da coluna que contém o código do município.') | |
if nova_coluna.__class__ == int: | |
coluna_cod_mun = nova_coluna+1 | |
def print_initial_message(self): | |
self.text.insert(END, u"» Este programa ajusta um arquivo em Excel para o formato esperado pelo Mapa Estático do SIM-PR.\n", ("blue_white",)) | |
self.text.insert(END, u"» Até o momento ele funciona somente para o programa Minha Casa Minha Vida.\n", ("blue_white",)) | |
self.text.insert(END, u"» O arquivo em excel pode conter algumas variáveis que serão substituídas pelos valores correspondentes, observando-se o código do município.\n", ("blue_white",)) | |
self.text.insert(END, u"» tais variáveis são:\n", ("blue_white",)) | |
self.atualiza_de_para() | |
for i in self.de_para.keys(): | |
self.text.insert(END, " - "+i+"\n", ("blue_white",)) | |
self.text.insert(END, u"» Modo de usar:\n", ("blue_white",)) | |
self.text.insert(END, u"» Selecione o arquivo em excel a ser trabalhado. O pograma criará na mesma pasta em que o arquivo está uma série de outros arquivos, em csv. A última coluna será considerada um separador. Será criado um arquivo em csv para cada valor único da última coluna (à exceção da primeira linha). Isto será feito para cada planilha constante do arquivo. Os arquivos em csv resultantes serão nomeados com uma junção do nome do arquivo mais o nome da planilha mais o nome do valor único da última coluna.\n", ("blue_white",)) | |
self.text.insert(END, u"» ATENÇÃO: Caso existam arquivos com nomes idênticos aos que serão criados, eles serão sobrescritos.\n", ("blue_white",)) | |
def help(self): | |
tkMessageBox.showinfo("Ajuda", u"Selecione a Planilha Excel na qual você pretende aplicar o script.") | |
def about(self): | |
tkMessageBox.showinfo("Sobre", u"Script para preparação de planilhas do programa MCMV.") | |
def open_dados_a_trabalhar(self): | |
self.source_file = tkFileDialog.askopenfilename(filetypes=[('Excel 1997 - 2000', '*.xls'),]) | |
wb = xlrd.open_workbook(self.source_file) | |
self.resultados = {} | |
for i in wb.sheet_names(): | |
sheet = wb.sheet_by_name(i) | |
self.cabecalho = [] | |
self.operacao_selecionada = {} | |
for ii in sheet.row_values(0): | |
self.cabecalho.append(ii) | |
self.operacao_selecionada[ii] = [None,None,None,None] | |
if self.source_file: | |
self.status.set("Fonte de dados: "+self.source_file) | |
self.atualiza_colunas() | |
def open_dados_municipais(self): | |
self.dados_municipais = tkFileDialog.askopenfilename(filetypes=[('Texto CSV', '*.csv'),]) | |
self.atualiza_de_para() | |
self.text.insert(END, u"» Um novo arquivo de dados municipais foi selecionado. As variáveis disponíveis agora são:\n", ("blue_white",)) | |
self.atualiza_de_para() | |
for i in self.de_para.keys(): | |
self.text.insert(END, " - "+i+"\n", ("blue_white",)) | |
def atualiza_colunas(self): | |
self.listbox.delete(0, END) | |
counter =0 | |
for i in self.cabecalho: | |
self.listbox.insert(END, str(counter)+" - "+i) | |
counter+=1 | |
for i in self.niveis_operacoes: | |
i.delete(0,END) | |
for i in self.operacoes_disponiveis: | |
for ii in self.niveis_operacoes: | |
ii.insert(END, i) | |
def aplicar_script(self): | |
self.text.yview(END) | |
fonte_de_dados = self.dados_municipais or self.dados_municipais_padrao | |
criar_resultado = [] | |
excelfile = self.source_file | |
dic_populacao= {} | |
for i in self.populacao: | |
dic_populacao[i[0]] = i | |
planilhas = {} | |
if excelfile: | |
self.text.insert(END, u"\n\n\n» ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ \n\n\n", ("blue_white",)) | |
self.text.insert(END, u"» Arquivo a ser trabalhado: "+excelfile+"\n", ("blue_white",)) | |
self.text.insert(END, u"» Arquivos resultantes: \n", ("blue_white",)) | |
#Extrai do excel | |
wb = xlrd.open_workbook(excelfile) | |
resultados = {} | |
for i in wb.sheet_names(): | |
sheet = wb.sheet_by_name(i) | |
planilhas[i] = [] | |
primeira_linha = True | |
cabecalho = [] | |
for rownum in range(sheet.nrows): | |
if primeira_linha: | |
for ii in sheet.row_values(rownum): | |
cabecalho.append(ii) | |
primeira_linha = False | |
if len(criar_resultado)<1: | |
criar_resultado.append(cabecalho) | |
else: | |
linha = [] | |
contador = 0 | |
for ii in sheet.row_values(rownum): | |
if contador==2: | |
cod_mun = int(ii) | |
if unicode(ii) in self.de_para.keys(): | |
#print ii | |
#print dic_populacao[unicode(cod_mun)][self.de_para[unicode(ii)]] | |
linha.append(dic_populacao[unicode(cod_mun)][self.de_para[unicode(ii)]]) | |
else: | |
linha.append(ii) | |
contador +=1 | |
#linha.append(ii) | |
nome = excelfile[:-4]+'_'+i+'_'+unicode(linha[-1]) | |
if nome not in resultados.keys(): | |
resultados[nome] = [] | |
resultados[nome].append(cabecalho) | |
resultados[nome].append(linha) | |
criar_resultado.append(linha) | |
for r in resultados.keys(): | |
atual = resultados[r] | |
nome_arquivo = r+'.csv' | |
self.text.insert(END, " - "+nome_arquivo+"\n", ("blue_white",)) | |
csvfile = UnicodeWriter(open(nome_arquivo, 'w')) | |
for ii in atual: | |
csvfile.writerow(ii) | |
else: | |
print "It is necessary to provide a xls file." | |
arquivo_resultado = UnicodeWriter(open(excelfile[:-4]+"_resultado.csv", 'w')) | |
self.resultados = criar_resultado | |
#for ii in criar_resultado: | |
# arquivo_resultado.writerow(ii) | |
arquivo_resultado = [] | |
def printhelp(self): | |
print 'Usage: call the script followed by a xls file. The script will create one csv with , and " separators and utf-8 encoding for each sheet in the file.' | |
def atualiza_de_para(self): | |
self.text.yview(END) | |
fonte_de_dados = self.dados_municipais or self.dados_municipais_padrao | |
try: | |
#print fonte_de_dados | |
self.populacao = [i for i in unicode_csv_reader(open(fonte_de_dados))] | |
self.de_para ={} | |
for i in range(len(self.populacao[0])): | |
self.de_para[self.populacao[0][i]] = i | |
except: | |
self.populacao = [] | |
self.de_para = {} | |
self.text.insert(END, u"» ATENÇÃO: NÃO HÁ FONTE DE DADOS MUNICIPAIS DISPONÍVEL. O SCRIPT NÃO FUNCIONARÁ CORRETAMENTE. \n", ("blue_white",)) | |
self.text.insert(END, u"» Antes de tentar rodar o script selecione uma fonte de dados municipais. \n", ("blue_white",)) | |
def action_listbox(self, args): | |
print self.operacao_selecionada[self.cabecalho[int(self.listbox.curselection()[0])]] | |
for i in self.niveis_operacoes: | |
i.selection_clear(0, END) | |
valor_atual = self.operacao_selecionada[self.cabecalho[int(self.listbox.curselection()[0])]] | |
for i in range(4): | |
if valor_atual[i] is not None: | |
self.niveis_operacoes[i].selection_set(valor_atual[i]) | |
def action_operacao_listbox(self, args): | |
contador = 0 | |
for i in self.niveis_operacoes: | |
if len(i.curselection())>0: | |
self.operacao_selecionada[self.cabecalho[int(self.listbox.curselection()[0])]][contador] = i.curselection()[0] | |
contador+=1 | |
self.agregada_text.config(state=NORMAL) | |
self.agregada_text.delete("1.0",END) | |
for i in self.operacao_selecionada.keys(): | |
for ii in self.operacao_selecionada[i]: | |
if ii is not None and ii not in (0,"0"): | |
self.agregada_text.insert(END, i+'\n',("blue_white")) | |
break | |
self.agregada_text.config(state=DISABLED) | |
def agregar_por_regioes(self): | |
dicionario_regioes = { | |
1 : "Norte", | |
2 : "Nordeste", | |
3 : "Sudeste", | |
4 : "Sul", | |
5 : "Centro-Oeste", | |
} | |
dicionario_estados = { | |
12: "Acre ", 16: "Amapá", 13: "Amazonas", 15: "Pará", 11: "Rondônia", 14: "Roraima", 17: "Tocantins", | |
27: "Alagoas", 29: "Bahia",23: "Ceará", 21: "Maranhão", 25: "Paraíba", 26: "Pernambuco", 22: "Piauí", 24: "Rio Grande do Norte", 28: "Sergipe", | |
32: "Espírito Santo", 31: "Minas Gerais", 33: "Rio de Janeiro", 35: "São Paulo", | |
41: "Paraná", 43: "Rio Grande do Sul",42: "Santa Catarina", | |
53: "Distrito Federal", 52: "Goiás", 51: "Mato Grosso", 50: "Mato Grosso do Sul", | |
} | |
dicionario_linha_operacao = { | |
2: "Brasil", | |
3: "Região", | |
4: "Estado", | |
5: "Município", | |
} | |
totais = {'brasil':{},'regioes':{}} | |
linha = 1 | |
municipio_padrao = {} | |
consolidado = {} | |
for regiao in dicionario_regioes.keys(): | |
regiao_atual = Regiao(dicionario_regioes[regiao], regiao) | |
for estado in dicionario_estados.keys(): | |
if str(estado)[0] == str(regiao): | |
regiao_atual.itens[estado] = Regiao(dicionario_estados[estado], estado) | |
consolidado[regiao_atual.codigo] = regiao_atual | |
"""for codigo,regiao in consolidado.items(): | |
print "Regiao:" +regiao.nome | |
for cod_estado,estado in regiao.itens.items(): | |
print "Estado: "+estado.nome""" | |
contador = 1 | |
for linha in self.resultados: | |
if contador == 1: | |
cabecalho= linha | |
else: | |
codigo_municipio = linha[coluna_cod_mun] | |
regiao = str(codigo_municipio)[0] | |
estado = str(codigo_municipio)[:2] | |
codigo_municipio = str(linha[coluna_cod_mun])[:5] | |
#print "consolidado: "+str(consolidado) | |
#print "regiao: "+str(regiao) | |
#print "estado: "+str(estado) | |
municipio_atual = Regiao(linha[9], int(codigo_municipio)) | |
dic_linha = {} | |
#print zip(cabecalho, linha) | |
for chave,valor in zip(cabecalho,linha): | |
dic_linha[chave] = valor | |
municipio_atual.empreendimentos.append(dic_linha) | |
#print estado#str(codigo_municipio) | |
#print consolidado.keys() | |
if int(codigo_municipio) not in consolidado[int(regiao)].itens[int(estado)].itens.keys(): | |
consolidado[int(regiao)].itens[int(estado)].itens[int(codigo_municipio)] = municipio_atual | |
contador +=1 | |
print len(consolidado) | |
for codigo,regiao in consolidado.items(): | |
print "Regiao:" +regiao.nome | |
for cod_estado,estado in regiao.itens.items(): | |
print " : "+estado.nome | |
for cod_mun,municipio in estado.itens.items(): | |
print " : "+municipio.nome | |
def callback(): | |
pass | |
root = Tk() | |
app = App(root) | |
root.mainloop() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment