-
Notifications
You must be signed in to change notification settings - Fork 0
/
Mini_projeto_v4.py
336 lines (280 loc) · 15.6 KB
/
Mini_projeto_v4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# Miniprojeto de Tkinter (Sistema de Cotação de Moedas)
import tkinter as tk # importa todo módulo Tkinter
import requests
from tkinter import ttk # Extensão para criação de lista suspensa (combobox)
from tkinter import *
import re
from datetime import datetime, timedelta
from tkinter.filedialog import askopenfilename
import pandas as pd
import os
# Cria um dicionário com os códigos das moedas disponíveis do awesome API
requisicao = requests.get('https://economia.awesomeapi.com.br/json/all')
requisicao = requisicao.json()
cod_moedas = {}
for item in requisicao:
for item2 in requisicao[item]:
if item2 == 'name':
cod_moedas[item] = requisicao[item]['name'].replace('/Real Brasileiro', '')
def periodo_cotacao(primeiro_dia, ultimo_dia):
# Dia inicial e dia final no formato "yyyy/mm/dd"
dia_inicial = datetime.strptime(primeiro_dia, "%Y/%m/%d")
dia_final = datetime.strptime(ultimo_dia, "%Y/%m/%d")
# Lista para armazenar os dias
dias_periodo = []
# Adiciona o dia inicial à lista
dias_periodo.append(dia_inicial)
# Incrementa um dia por vez e adiciona à lista até chegar ao dia final
while dia_inicial < dia_final:
dia_inicial += timedelta(days=1)
dias_periodo.append(dia_inicial)
# Formata os dias para o período usado
for i, dia in enumerate(dias_periodo):
dias_periodo[i] = dia.strftime("%d/%m/%y")
return dias_periodo
# Fç que transforma a data de um formatdo de entrada para outro de saída
def formata_data(data, formato_entrada, formato_saida="%Y/%m/%d"):
data_formatada = datetime.strptime(data, formato_entrada)
data_formatada = data_formatada.strftime(formato_saida)
return data_formatada
# Lista contendo os possíveis formatos de data
formato_data = ["YYYY-MM-DD", "DD-MM-YYYY", "DD/MM/YYYY", "YYYY/MM/DD", "DD/MM/YY", "DD-MM-YY"]
# Verifica se a data pertence a algum dos 4 padrões de data e, caso, positivo, retorna a data num formato padrão
# ("%Y/%m/%d")
def verificar_formato_data(data, formato):
for u in formato:
if u == "DD-MM-YYYY":
padrao = r"\d{2}-\d{2}-\d{4}"
if re.fullmatch(padrao, data):
return True, formata_data(data, "%d-%m-%Y")
elif u == "DD/MM/YYYY":
padrao = r"\d{2}/\d{2}/\d{4}"
if re.fullmatch(padrao, data):
return True, formata_data(data, "%d/%m/%Y")
elif u == "YYYY/MM/DD":
padrao = r"\d{4}/\d{2}/\d{2}"
if re.fullmatch(padrao, data):
return True, formata_data(data, "%Y/%m/%d")
elif u == "YYYY-MM-DD":
padrao = r"\d{4}-\d{2}-\d{2}"
if re.fullmatch(padrao, data):
return True, formata_data(data, "%Y-%m-%d")
elif u == "DD-MM-YY":
padrao = r"\d{2}-\d{2}-\d{2}"
if re.fullmatch(padrao, data):
return True, formata_data(data, "%d-%m-%y")
elif u == "DD/MM/YY":
padrao = r"\d{2}/\d{2}/\d{2}"
if re.fullmatch(padrao, data):
return True, formata_data(data, "%d/%m/%y")
else:
return False, None
# Função que transforma timestamp em data
def transforma_timestamp(tmstp):
data_real = datetime.fromtimestamp(int(tmstp))
data_real = data_real.strftime('%d/%m/%y')
return data_real
# Função para filtrar os itens da lista suspensa
def filter_combobox(*args):
typed_text = moeda_var.get()
filtered_items = []
for v in moedas:
if typed_text.lower() in v.lower():
filtered_items.append(v)
moeda['values'] = filtered_items
# Função que realiza o pedido de request
def realizar_request(url):
headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) "
"Chrome/114.0.5735.199 Safari/537.36"}
try:
response = requests.get(url, headers=headers)
response.raise_for_status() # Verifica se houve algum erro na resposta
return response.json()
except requests.exceptions.HTTPError as errh:
print("Erro HTTP:", errh)
except requests.exceptions.ConnectionError as errc:
print("Erro de conexão:", errc)
except requests.exceptions.Timeout as errt:
print("Timeout de conexão:", errt)
except requests.exceptions.RequestException as err:
print("Erro durante a solicitação:", err)
return None
# Função para buscar a cotação da API, onde cod_moeda é o cod da moeda, di é o dia inicial e df o dia final
def awesome_api(cod_moeda, di, df):
print(cod_moeda)
hj = datetime.now() # Pega a data de hoje
data_hj = hj.strftime("%Y/%m/%d")
print(data_hj)
if verificar_formato_data(di, formato_data)[0] and verificar_formato_data(df, formato_data)[0]:
if type(cod_moeda) != list: # COTAÇÃO ESPECÍFICA (não é lista)
if verificar_formato_data(di, formato_data)[1] > data_hj or verificar_formato_data(df, formato_data)[1] > \
data_hj: # Dia selecionado superior ao dia de hj
mensagem_cotacao = tk.Label(text="Data selecionada superior a data de hoje!", fg='black', bg='#b0e0e6')
mensagem_cotacao.grid(row=3, column=0, columnspan=2, sticky="NSEW") # Adiciona o label à janela
elif data_hj == verificar_formato_data(di, formato_data)[1]: # Se a data selecionada for igual ao dia de hj
url_hoje = 'https://economia.awesomeapi.com.br/last/' + cod_moeda
cotacao = realizar_request(url_hoje)[cod_moeda + 'BRL']['bid']
else: # Se a data selecionada não for o dia de hj
dia = verificar_formato_data(di, formato_data)[1].replace('/', '')
url_diario = f"https://economia.awesomeapi.com.br/json/daily/" \
f"{cod_moeda}-BRL?start_date={dia}&end_date={dia}"
cotacao = realizar_request(url_diario)[0]['bid']
return cotacao
else: # MÚLTIPLAS COTAÇÕES (o número máximo de resultados é 360)
dia1 = verificar_formato_data(di, formato_data)[1]
dia2 = verificar_formato_data(df, formato_data)[1]
# Se os dias solicitados forem maiores que o atual, a cotação será buscada até o dia atual
if dia1 > data_hj:
dia1 = data_hj
if dia2 > data_hj:
dia2 = data_hj
periodo = periodo_cotacao(dia1, dia2) # Cria uma lista do período da cotação
mult_cotacoes = []
for cod in cod_moeda:
dia1 = dia1.replace('/', '')
dia2 = dia2.replace('/', '')
url_mult = f"https://economia.awesomeapi.com.br/json/daily/{cod}-BRL/" \
f"360?start_date={dia1}&end_date={dia2}"
cotacoes = realizar_request(url_mult)
cotacao_moeda = len(periodo)*['']
for cotacao in cotacoes:
print('cotacao', cotacao)
data_transf = transforma_timestamp(cotacao['timestamp'])
for i, dia in enumerate(periodo):
if dia == data_transf:
cotacao_moeda[i] = float(cotacao['bid'])
print(cotacao_moeda)
# Caso a API não retorne uma cotação, é feito um request específico para os dias faltantes
for i, cotacao in enumerate(cotacao_moeda):
if cotacao == '':
dia = formata_data(periodo[i], "%d/%m/%y", "%Y/%m/%d").replace('/', '')
url_diario = f"https://economia.awesomeapi.com.br/json/daily/" \
f"{cod}-BRL?start_date={dia}&end_date={dia}"
try: # Caso a cotação não seja pega no request do período
cotacao_moeda[i] = float(realizar_request(url_diario)[0]['bid'])
except IndexError: # Caso o dia pleiteado seja final de semana
cotacao_moeda[i] = cotacao_moeda[i - 1]
mult_cotacoes.append(cotacao_moeda)
cotacao_moeda.insert(0, cod)
cotacao_moeda = len(periodo) * ['']
periodo.insert(0, 'Data')
mult_cotacoes.insert(0, periodo)
# print(mult_cotacoes)
return mult_cotacoes
# Função que busca a cotação para a moeda e data selecionadas qdo a tecla "Pegar Cotação for acionada
def buscar_cotacao():
moeda_preenchida = moeda.get()
data_preenchida = data_cotacao.get()
if moeda_preenchida and data_preenchida: # A rotina não continua se a moeda e data não foram selecionadas
print('moeda preenchida', moeda_preenchida)
for cod in cod_moedas:
if cod_moedas[cod] == moeda_preenchida:
cod_moeda = cod
print(cod_moeda)
mensagem_cotacao = tk.Label(text="Cotação não encontrada", fg='black', bg='#b0e0e6') # Texto de msg não
# encontrada
mensagem_cotacao.grid(row=3, column=0, columnspan=2, sticky="NSEW") # Adiciona o label à janela
if cod_moeda:
cotacao = awesome_api(cod_moeda, data_preenchida, data_preenchida)
# Altera o label mensagem_cotaçao
mensagem_cotacao["text"] = f'Cotação do {moeda_preenchida} é de {cotacao} reais'
else:
mensagem_cotacao = tk.Label(text="Moeda ou data não preenchidas", fg='black', bg='#b0e0e6')
mensagem_cotacao.grid(row=3, column=0, columnspan=2, sticky="NSEW") # Adiciona o label à janela
lst_moedas = [] # Será uma variável global para conectar a fç selecionar_arquivo() e atualizar_cotacao()
# Função que abre uma janela para selecionar o arquivo desejado
def selecionar_arquivo():
global lst_moedas
try:
caminho_arquivo = askopenfilename(title="Selecione um arquivo em Excel para abrir")
df = pd.read_excel(caminho_arquivo)
mensagem_caminho_arquivo_entrada['text'] = caminho_arquivo # Atualiza o caminho do arquivo
lst_moedas = list(df.iloc[:, 0])
return lst_moedas
except:
mensagem_caminho_arquivo_entrada['text'] = 'Arquivo inválido!'
# Função que atualiza as cotações para as moedas selecionadas
def atualizar_cotacao():
global lst_moedas
print(lst_moedas)
data_inicial_preenchida = data_inicial.get()
data_final_preenchida = data_final.get()
if data_inicial_preenchida and data_final_preenchida: # A rotina não continua se moeda/ data não forem selecionadas
mult_cotacoes = awesome_api(lst_moedas, data_inicial_preenchida, data_final_preenchida)
df = pd.DataFrame(mult_cotacoes) # Cria um DataFrame para incluir as infos de cotação
# Salva o DataFrame num arquivo do Excel
df.to_excel(f'mult_cotacoes{datetime.now().strftime("%d/%m/%y/%H/%M/%S").replace("/","")}.xlsx', index=False)
mensagem_arquivo_atualizado["text"] = "Arquivo de moedas atualizado com sucesso."
# inicia janela
janela = tk.Tk()
# Criar a variável de controle do combobox
moeda_var = StringVar()
# Cria uma lista suspensa (janela é onde irá aparecer a lista suspensa e values é a lista de valores)
moeda = ttk.Combobox(janela, textvariable=moeda_var)
moeda.grid(row=1, column=2, padx=10, pady=10, sticky="NSEW")
# Insere título da janela
janela.title("Sistema de Cotação de Moedas")
# Configura a cor do backgorund da janela
janela.configure(bg='#b0e0e6')
# Ajuste automático de linha(s) e coluna(s)
janela.rowconfigure([0, 12], weight=1)
janela.columnconfigure(2, weight=1)
# Cotação de 1 moeda específica
titulo1 = tk.Label(text="Cotação de 1 moeda específica", fg='black', bg='#b0e0e6', borderwidth=2, relief='solid')
titulo1.grid(row=0, column=0, padx=10, pady=10, columnspan=3, sticky="NSEW")
# Seleciona moeda
mensagem2 = tk.Label(text="Selecione a moeda que deseja consultar:", fg='black', bg='#b0e0e6')
mensagem2.grid(row=1, column=0, padx=10, pady=10, columnspan=2, sticky="NSEW")
# Insere data
mensagem3 = tk.Label(text="Selecione o dia (DD/MM/AA) que deseja pegar a cotação:", fg='black', bg='#b0e0e6')
mensagem3.grid(row=2, column=0, padx=10, pady=10, columnspan=2, sticky="NSEW")
# Insere uma caixa de texto para que o usuário insira a data
data_cotacao = tk.Entry(fg='black', bg='white')
data_cotacao.grid(row=2, column=2, padx=10, pady=10, sticky="NSEW")
# Insere uma caixa de text para amsg de cotação
mensagem_cotacao = tk.Label(text="", fg='black', bg='#b0e0e6')
mensagem_cotacao.grid(row=3, column=0, columnspan=2, padx=10, pady=10, sticky="NSEW") # Adiciona o label à janela
# Cria uma lista com as chaves do dicionário
moedas = []
for item in cod_moedas:
moedas.append(cod_moedas[item])
moeda['values'] = moedas
# Configurar a função de filtro para ser chamada sempre que o usuário digitar algo
moeda_var.trace('w', filter_combobox)
# Botão de busca da cotação
botao_buscar_cotacao = tk.Button(text="Pegar Cotação", fg='black', bg='#b0e0e6', command=buscar_cotacao)
botao_buscar_cotacao.grid(row=3, column=2, padx=10, pady=10,) # Adiciona o botão na janela
# Cotação de Múltiplas Moedas
titulo2 = tk.Label(text="Cotação de Múltiplas Moedas", fg='black', bg='#b0e0e6', borderwidth=2, relief='solid')
titulo2.grid(row=5, column=0, columnspan=3, padx=10, pady=10, sticky="NSEW")
# Seleciona arquivo
mensagem_selecionar_arquivo = tk.Label(text="Selecione um arquivo em Excel com as moedas na coluna A:", fg='black',
bg='#b0e0e6')
mensagem_selecionar_arquivo.grid(row=6, column=0, columnspan=2, padx=10, pady=10, sticky="NSEW")
# Botão para selecionar o arquivo
botao_selecionar_arquivo = tk.Button(text="Clique aqui para selecionar", fg='black', bg='#b0e0e6',
command=selecionar_arquivo)
botao_selecionar_arquivo.grid(row=6, column=2, padx=10, pady=10) # Adiciona o botão na janela
# Caminho do arquivo
mensagem_caminho_arquivo_entrada = tk.Label(text="Nenhum arquivo selecionado", fg='black', bg='#b0e0e6', anchor='e')
mensagem_caminho_arquivo_entrada.grid(row=7, column=0, columnspan=3, padx=10, pady=10, sticky="NSEW")
# Seleciona datas inicial e final
mensagem_data_inicial = tk.Label(text="Data Inicial (DD/MM/AA):", fg='black', bg='#b0e0e6')
mensagem_data_inicial.grid(row=8, column=0, sticky="NSEW")
data_inicial = tk.Entry(fg='black', bg='white') # Caixa txt data inicial
data_inicial.grid(row=8, column=2)
mensagem_data_final = tk.Label(text="Data Final (DD/MM/AA):", fg='black', bg='#b0e0e6')
mensagem_data_final.grid(row=9, column=0, padx=10, pady=10, sticky="NSEW")
data_final = tk.Entry(fg='black', bg='white') # Caixa txt data final
data_final.grid(row=9, column=2, padx=10, pady=10)
# Botão para atualizar cotações
botao_atualizar_cotacao = tk.Button(text="Atualizar Cotações", fg='black', bg='#b0e0e6', command=atualizar_cotacao)
botao_atualizar_cotacao.grid(row=11, column=0, padx=10, pady=10) # Adiciona o botão na janela
# Msg de arquivo atualizado
mensagem_arquivo_atualizado = tk.Label(text="", fg='black', bg='#b0e0e6')
mensagem_arquivo_atualizado.grid(row=11, column=1, padx=10, pady=10, columnspan=2, sticky="NSEW")
# Botão para fechar programa
botao_fechar_programa = tk.Button(text="Fechar", fg='black', bg='#b0e0e6', command=janela.quit)
botao_fechar_programa.grid(row=12, column=2, padx=10, pady=10) # Adiciona o botão na janela
# Roda o código continuamente permitindo que a janela fique continuamente na tela
janela.mainloop()