{"id":531,"date":"2024-08-14T12:05:48","date_gmt":"2024-08-14T15:05:48","guid":{"rendered":"https:\/\/www.gpscompany.com.br\/newsite\/?p=531"},"modified":"2025-01-17T14:52:57","modified_gmt":"2025-01-17T17:52:57","slug":"importacao-direta-de-arquivos-ofx-no-power-bi","status":"publish","type":"post","link":"https:\/\/www.gpscompany.com.br\/newsite\/2024\/08\/14\/importacao-direta-de-arquivos-ofx-no-power-bi\/","title":{"rendered":"Importa\u00e7\u00e3o Direta de Arquivos OFX no Power BI"},"content":{"rendered":"\n<div class=\"wp-block-group alignfull bodyText has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\">\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile bodyImg\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"574\" src=\"https:\/\/www.gpscompany.com.br\/newsite\/wp-content\/uploads\/2024\/08\/StockCake-Childs-Astonished-Gaze_1723642130-1024x574.webp\" alt=\"\" class=\"wp-image-537 size-full\" srcset=\"https:\/\/www.gpscompany.com.br\/newsite\/wp-content\/uploads\/2024\/08\/StockCake-Childs-Astonished-Gaze_1723642130-1024x574.webp 1024w, https:\/\/www.gpscompany.com.br\/newsite\/wp-content\/uploads\/2024\/08\/StockCake-Childs-Astonished-Gaze_1723642130-300x168.webp 300w, https:\/\/www.gpscompany.com.br\/newsite\/wp-content\/uploads\/2024\/08\/StockCake-Childs-Astonished-Gaze_1723642130-768x430.webp 768w, https:\/\/www.gpscompany.com.br\/newsite\/wp-content\/uploads\/2024\/08\/StockCake-Childs-Astonished-Gaze_1723642130.webp 1456w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<p style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.708), 1.3rem);\">O Power BI n\u00e3o est\u00e1 preparado para lidar de forma nativa com a importa\u00e7\u00e3o de arquivos OFX, um padr\u00e3o usado por muitos bancos para envio de extratos. No entanto, isso n\u00e3o significa que n\u00e3o possamos importar esses arquivos diretamente. Com um pouco de criatividade, \u00e9 poss\u00edvel resolver esse problema e criar um leitor de OFX sem a necessidade de convers\u00f5es para CSV ou XML em programas externos.<\/p>\n<\/div><\/div>\n\n\n\n<p style=\"font-size:0.5em\"><a href=\"https:\/\/stockcake.com\/i\/child-s-astonished-gaze_987531_785532\">Photo by Stockcake<\/a><\/p>\n\n\n\n<div class=\"wp-block-group alignwide is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\n<p class=\"has-text-align-center\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.542), 1.2rem);\">Abaixo, apresento um script em M Language que realiza a leitura de um arquivo OFX do Banco do Brasil. Este exemplo pode servir de inspira\u00e7\u00e3o para lidar com esse tipo de arquivo:<\/p>\n<\/div>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>let\n\n    pFile = \"C:\\temp\\Extrato.ofx\",\n\n    Fonte = Csv.Document(File.Contents(pFile),&#91;Encoding=1252, QuoteStyle=QuoteStyle.None]),\n    #\"Tipo Alterado\" = Table.TransformColumnTypes(Fonte,{{\"Column1\", type text}}),\n\n    Mod001 =\n      Table.ReorderColumns(\n            Table.FillDown(\n        Table.ReplaceValue(\n      Table.AddIndexColumn(\n       Table.RemoveColumns(\n          Table.SelectRows(\n           Table.AddColumn(\n    Table.TransformColumns(\n           Table.AddColumn(\n           Table.AddColumn( Table.SelectRows(#\"Tipo Alterado\", each Text.Contains(&#91;#\"Column1\"],\"&lt;\"))\n                          , \"Column2\", each Text.BetweenDelimiters(&#91;Column1],\"&lt;\",\"&gt;\"), type text)\n                          , \"Column3\", each Text.AfterDelimiter(&#91;Column1],\"&gt;\"), type text)\n                          , {{\"Column3\", each try Text.BeforeDelimiter(_,\"&lt;\")  otherwise _ , type text}})\n                          , \"Column4\", each if List.Contains({\"SIGNONMSGSRSV1\",\"BANKMSGSRSV1\",\"STMTTRN\",\"LEDGERBAL\"},&#91;Column2]) then &#91;Column2] else null, type text)\n                          , each Text.StartsWith(Text.Trim(&#91;Column1]) ,\"&lt;\/\") = false and &#91;Column1] &lt;&gt; \"&lt;OFX&gt;\")\n                          , {\"Column1\"})\n                          , \"Column1\",1,1)\n                          , each &#91;Column1] , each if &#91;Column4] = null then null else &#91;Column1], Replacer.ReplaceValue, {\"Column1\"})\n                          , {\"Column4\",\"Column1\"})\n                          , {\"Column1\",\"Column2\",\"Column3\",\"Column4\"}),\n\n\n    getData = (dbOFX,pBloco,pID) =&gt;\n    Table.PromoteHeaders(\n         Table.Transpose(\n        Table.SelectRows( dbOFX\n                        , each &#91;Column4] = pBloco and &#91;Column1] = pID and &#91;Column3]&lt;&gt;\"\")&#91;&#91;Column2],&#91;Column3]])\n                        ),\n\n    Mod002 = \n    Table.AddColumn(\n        Table.Group( Mod001 \n                   , {\"Column1\",\"Column4\"}\n                   , {{\"Data\", each _, type table &#91;Column1=number, Column2=text, Column3=text, Column4=text]}})\n                   , \"Data1\", each getData(&#91;Data],&#91;Column4],&#91;Column1]), type table)&#91;&#91;Column4],&#91;Data1]]\nin\n    Mod002<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<p>Vamos detalhar o nosso c\u00f3digo.<br><br><strong>1 \u2013 Defini\u00e7\u00e3o do Arquivo e Leitura:<\/strong><\/p>\n<\/div>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>let\n    pFile = \"C:\\temp\\Extrato.ofx\",\n    Fonte = Csv.Document(File.Contents(pFile), &#91;Encoding=1252, QuoteStyle=QuoteStyle.None]),\n    #\"Tipo Alterado\" = Table.TransformColumnTypes(Fonte, {{\"Column1\", type text}}),<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<ul class=\"wp-block-list\">\n<li>pFile: Define o caminho do arquivo OFX.<\/li>\n\n\n\n<li>Fonte: L\u00ea o conte\u00fado do arquivo como um documento CSV com codifica\u00e7\u00e3o 1252 (ANSI) e sem estilos de cita\u00e7\u00e3o.<\/li>\n\n\n\n<li>\u201dTipo Alterado\u201d: Transforma o tipo da coluna Column1 para texto.<\/li>\n<\/ul>\n\n\n\n<p><strong>2 \u2013 Transforma\u00e7\u00e3o dos Dados<\/strong>:<\/p>\n<\/div>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>Mod001 =\n      Table.ReorderColumns(\n            Table.FillDown(\n        Table.ReplaceValue(\n      Table.AddIndexColumn(\n       Table.RemoveColumns(\n          Table.SelectRows(\n           Table.AddColumn(\n    Table.TransformColumns(\n           Table.AddColumn(\n           Table.AddColumn( Table.SelectRows(#\"Tipo Alterado\", each Text.Contains(&#91;#\"Column1\"],\"&lt;\"))\n                          , \"Column2\", each Text.BetweenDelimiters(&#91;Column1],\"&lt;\",\"&gt;\"), type text)\n                          , \"Column3\", each Text.AfterDelimiter(&#91;Column1],\"&gt;\"), type text)\n                          , {{\"Column3\", each try Text.BeforeDelimiter(_,\"&lt;\")  otherwise _ , type text}})\n                          , \"Column4\", each if List.Contains({\"SIGNONMSGSRSV1\",\"BANKMSGSRSV1\",\"STMTTRN\",\"LEDGERBAL\"},&#91;Column2]) then &#91;Column2] else null, type text)\n                          , each Text.StartsWith(Text.Trim(&#91;Column1]) ,\"&lt;\/\") = false and &#91;Column1] &lt;&gt; \"&lt;OFX&gt;\")\n                          , {\"Column1\"})\n                          , \"Column1\",1,1)\n                          , each &#91;Column1] , each if &#91;Column4] = null then null else &#91;Column1], Replacer.ReplaceValue, {\"Column1\"})\n                          , {\"Column4\",\"Column1\"})\n                          , {\"Column1\",\"Column2\",\"Column3\",\"Column4\"}),<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<ul class=\"wp-block-list\">\n<li>Mod001: Realiza uma s\u00e9rie de transforma\u00e7\u00f5es nos dados:\n<ul class=\"wp-block-list\">\n<li><em>Table.SelectRows<\/em>: Seleciona apenas as linhas que cont\u00eam tags XML (&lt;), excluindo linhas de fechamento (&lt;\/) e a tag &lt;OFX&gt;.<\/li>\n\n\n\n<li><em>Table.AddColumn<\/em>: Cria colunas adicionais (Column2, Column3) para extrair informa\u00e7\u00f5es entre delimitadores &lt; &gt; e ap\u00f3s &gt;.<\/li>\n\n\n\n<li>T<em>able.TransformColumns<\/em>: Manipula a coluna Column3, tentando extrair o conte\u00fado antes do delimitador &lt;, se poss\u00edvel.<\/li>\n\n\n\n<li><em>Table.ReplaceValue<\/em>: Substitui valores na coluna Column1 com base em condi\u00e7\u00f5es espec\u00edficas.<\/li>\n\n\n\n<li><em>Table.AddIndexColumn<\/em>: Adiciona uma coluna de \u00edndice \u00e0s tabelas resultantes.<\/li>\n\n\n\n<li><em>Table.RemoveColumns<\/em>: Remove colunas n\u00e3o necess\u00e1rias.<\/li>\n\n\n\n<li><em>Table.FillDown<\/em>: Preenche valores para baixo em colunas onde os valores s\u00e3o nulos.<\/li>\n\n\n\n<li><em>Table.ReorderColumns<\/em>: Reordena as colunas para uma ordem espec\u00edfica.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>3 \u2013&nbsp;<strong>Fun\u00e7\u00e3o personalizada&nbsp;<em>getData<\/em><\/strong>:<\/p>\n<\/div>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>    getData = (dbOFX,pBloco,pID) =&gt;\n    Table.PromoteHeaders(\n         Table.Transpose(\n        Table.SelectRows( dbOFX\n                        , each &#91;Column4] = pBloco and &#91;Column1] = pID and &#91;Column3]&lt;&gt;\"\")&#91;&#91;Column2],&#91;Column3]])\n                        ),<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<ul class=\"wp-block-list\">\n<li>getData: Define uma fun\u00e7\u00e3o que recebe tr\u00eas par\u00e2metros (dbOFX, pBloco, pID):\n<ul class=\"wp-block-list\">\n<li><em>Table.SelectRows<\/em>: Seleciona as linhas onde Column4 \u00e9 igual a pBloco, Column1 \u00e9 igual a pID e Column3 n\u00e3o est\u00e1 vazio.<\/li>\n\n\n\n<li><em>Table.Transpose<\/em>: Transp\u00f5e a tabela resultante.<\/li>\n\n\n\n<li><em>Table.PromoteHeaders<\/em>: Promove a primeira linha como cabe\u00e7alhos da tabela.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>4 \u2013 Combinando e Agrupando os Dados<\/strong>:<\/p>\n<\/div>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>    Mod002 = \n    Table.AddColumn(\n        Table.Group( Mod001 \n                   , {\"Column1\",\"Column4\"}\n                   , {{\"Data\", each _, type table &#91;Column1=number, Column2=text, Column3=text, Column4=text]}})\n                   , \"Data1\", each getData(&#91;Data],&#91;Column4],&#91;Column1]), type table)&#91;&#91;Column4],&#91;Data1]]<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<ul class=\"wp-block-list\">\n<li>Mod002: Agrupa os dados de Mod001 usando Table.Group, agrupando por Column1 e Column4.\n<ul class=\"wp-block-list\">\n<li><em>Table.AddColumn<\/em>: Adiciona uma coluna calculada Data1, que aplica a fun\u00e7\u00e3o getData aos grupos de dados.<\/li>\n\n\n\n<li>Retorna apenas as colunas&nbsp;<em>Column4<\/em>&nbsp;e&nbsp;<em>Data1<\/em>&nbsp;como resultado final.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>5 \u2013 Retorno do Resultado Final:<\/strong><\/p>\n\n\n\n<p><\/p>\n<\/div>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>in\n    Mod002<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<ul class=\"wp-block-list\">\n<li>Retorna Mod002 como o resultado final do script.<\/li>\n<\/ul>\n\n\n\n<p>Este script em M Language \u00e9 projetado para processar arquivos OFX do Banco do Brasil, realizando v\u00e1rias transforma\u00e7\u00f5es nos dados para prepar\u00e1-los para an\u00e1lise posterior no Power BI. Ele extrai informa\u00e7\u00f5es espec\u00edficas de tags OFX, promove cabe\u00e7alhos e organiza os dados em uma estrutura adequada para an\u00e1lise e visualiza\u00e7\u00e3o.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group alignwide is-vertical is-layout-flex wp-container-core-group-is-layout-fe9cc265 wp-block-group-is-layout-flex\">\n<p>Desejamos que o conte\u00fado tenha sido \u00fatil para o seu aprendizado.<br>\u2013 Fonte de mat\u00e9ria site <a href=\"https:\/\/ornit.com.br\/site\/importacao-direta-de-arquivos-ofx-no-power-bi\/\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0);color:#0099ff\" class=\"has-inline-color\">ornit.com.br<\/mark><\/strong><\/a> \ud83d\ude09.<\/p>\n<\/div>\n\n\n\n<p><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>O Power BI n\u00e3o est\u00e1 preparado para lidar de forma nativa com a importa\u00e7\u00e3o de arquivos OFX, um padr\u00e3o usado por muitos bancos para envio de extratos. No entanto, isso n\u00e3o significa que n\u00e3o possamos importar esses arquivos diretamente.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[8,18],"class_list":["post-531","post","type-post","status-publish","format-standard","hentry","category-power-bi","tag-power-bi","tag-power-query"],"_links":{"self":[{"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/posts\/531","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/comments?post=531"}],"version-history":[{"count":25,"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/posts\/531\/revisions"}],"predecessor-version":[{"id":1040,"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/posts\/531\/revisions\/1040"}],"wp:attachment":[{"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/media?parent=531"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/categories?post=531"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gpscompany.com.br\/newsite\/wp-json\/wp\/v2\/tags?post=531"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}