Created
August 21, 2025 02:08
-
-
Save tioback/c582223cbb4921bb3d077519f07551d1 to your computer and use it in GitHub Desktop.
Buscar dados de títulos do tesouro
This file contains hidden or 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
const URL_INVESTIR = "https://www.tesourodireto.com.br/documents/d/guest/rendimento-investir-csv?download=true"; | |
const URL_RESGATAR = "https://www.tesourodireto.com.br/documents/d/guest/rendimento-resgatar-csv?download=true"; | |
/** | |
* Busca um arquivo CSV direto do site do www.tesourodireto.com.br e converte pra um mapa usando nome do título | |
* convertido pra lower case como chave e as demais propriedades (nome, taxa, pu, vencimento) como valor. | |
*/ | |
function getData(urlCsv = URL_RESGATAR) { | |
const resp = UrlFetchApp.fetch(urlCsv, { muteHttpExceptions: true, followRedirects: true }); | |
if (resp.getResponseCode() !== 200) { | |
throw new Error("HTTP " + resp.getResponseCode() + " ao acessar CSV: " + urlCsv); | |
} | |
const text = resp.getContentText("UTF-8"); | |
const rows = Utilities.parseCsv(text, ";"); | |
if (!rows || rows.length < 2) { | |
throw new Error("CSV vazio ou sem dados."); | |
} | |
// descarta linha de títulos da resposta original | |
return new Map(rows.slice(1).map(row => [row[0].trim().toLowerCase(), { | |
nome: row[0].trim(), | |
taxa: row[1], | |
pu: row[2], | |
vencimento: row[3] | |
}])); | |
} | |
/** | |
* Retorna um array com os dados dos títulos do tesouro solicitados, diretamente do arquivo CSV disponibilizado | |
* no site do www.tesourodireto.com.br. | |
* | |
* Faz um distinct nos valores para não devolver dados repetidos. | |
* | |
* Modo de uso: | |
* | |
* =tesouroDiretoResgate("Tesouro IPCA+ 2029") | |
* =tesouroDiretoResgate(A3) | |
* =tesouroDiretoResgate(A3:A99) | |
* =tesouroDiretoResgate(A3:C10) | |
* | |
* @param titulos lista de títulos pra buscar os dados de resgate. | |
* @param incluirCabecalho (opcional) (padrão = true) retorna o cabeçalho dos dados como o primeiro elemento do | |
* array de resposta. | |
*/ | |
function tesouroDiretoResgate(titulos = [], incluirCabecalho = true) { | |
const titulosDistintos = new Set(); | |
if (!Array.isArray(titulos)) { | |
titulosDistintos.add(titulo); | |
} else { | |
titulos.forEach(titulo => Array.isArray(titulo) | |
? titulo.forEach(subtitulo => titulosDistintos.add(subtitulo)) | |
: titulosDistintos.add(titulo) | |
); | |
} | |
if (titulos.length === 0) { | |
throw new Error("Sem dados para pesquisar."); | |
} | |
if (Array.isArray(titulos[0])) { | |
titulos = titulos[0]; | |
} | |
const data = getData(); | |
const result = []; | |
if (incluirCabecalho) { | |
result.push(["Título", "Taxa", "PU", "Vencimento"]); | |
}; | |
const erros = []; | |
titulosDistintos.forEach(nomeTitulo => { | |
const chave = nomeTitulo.toLowerCase(); | |
const row = data.get(chave); | |
if (!row) { | |
erros.push(new Error("Título não encontrado: " + nomeTitulo)); | |
return; | |
} | |
result.push([ | |
row.nome, | |
convertePercentualPraDecimal(row.taxa), | |
Number.parseFloat(row.pu.substring(3).replaceAll(".", "").replaceAll(",", ".")), | |
row.vencimento | |
]); | |
}); | |
if (erros.length > 0 && result.length === incluirCabecalho ? 1 : 0) { | |
throw erros; | |
} | |
return result; | |
} | |
function convertePercentualPraDecimal(valor) { | |
const taxa = valor.replace(/\D*?(-?\d+(\.\d{3})*(,\d+)%?)/, "$1").replaceAll(".", "").replaceAll(",", "."); | |
if (taxa.indexOf("%") >= 0) { | |
return Number.parseFloat(taxa.replaceAll("%", "")) / 100; | |
} else { | |
return Number.parseFloat(taxa); | |
} | |
} | |
function testarResgateUm() { | |
tesouroDiretoResgate("Tesouro IPCA+ 2035"); | |
} | |
function testarResgateLista() { | |
tesouroDiretoResgate([ | |
["Tesouro Selic 2026"], | |
["Tesouro IPCA+ 2029"], | |
["Tesouro IPCA+ 2045"], | |
["Tesouro IPCA+ com Juros Semestrais 2035"] | |
]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment