Relatórios: Excel e cópias de segurança

O CRM passa a exportar os clientes para o Excel e a fazer (e restaurar) cópias de segurança de todos os dados. É o último código guiado: a partir daqui, o CRM é teu!

🎯 No fim desta aula vais conseguir

🧰 Antes de começar

  1. Abre a pasta meu-crm no VS Code e o index.html com o Live Server.
  2. Confirma que o painel da aula 15 funciona.
  3. Para testar bem os acentos, cria (ou edita) um cliente com letras portuguesas, por exemplo: nome João Gonçalves, empresa Pastelaria Ribeirão, notas Ligar às 10h; prefere email.
  4. Verifica se o computador tem o Excel. Se não tiver, serve o LibreOffice Calc ou o Google Sheets (vê as instruções no passo 4).

😕 Faltaste à aula 15 ou o teu projeto não funciona? Descarrega o ponto de controlo da aula 15, descompacta-o e trabalha a partir dele.

Parte A — A ideia: tirar os dados do CRM (e não os perder) (≈ 15 min)

💡 Relatórios: os dados têm de sair da aplicação

Numa empresa, os dados não ficam fechados dentro de uma aplicação. O chefe pede «manda-me a lista de clientes em Excel»; o contabilista quer os negócios ganhos do mês; o colega do marketing quer os emails dos leads. Por isso, quase todas as aplicações de gestão têm um botão Exportar. O formato mais universal para isso é o CSV.

CSV (Comma-Separated Values, «valores separados por vírgulas») é um ficheiro de texto simples em que:

Abre-se no Excel, no LibreOffice, no Google Sheets… e até no Bloco de Notas. O nosso vai ser assim:

Três pormenores importantes (que já estão tratados no código que vais copiar):

  1. Ponto e vírgula em vez de vírgula. Em Portugal, a vírgula é usada nos números decimais (12,50 €). Por isso, o Excel configurado em português espera ; a separar as colunas.
  2. Tudo entre aspas. Se as notas tiverem um ; (como «Ligar às 10h; prefere email»), as aspas dizem ao Excel que aquilo é tudo uma célula só. E se um valor tiver aspas lá dentro, escrevem-se duas seguidas ("") — é a regra do CSV.
  3. Os acentos. O computador guarda cada letra como um número. A tabela mais usada hoje, a UTF-8, tem todas as letras do mundo (e os emojis). Mas o Excel nem sempre adivinha que o ficheiro está em UTF-8 e pode mostrar «João» em vez de «João». A solução é pôr no início do ficheiro um carácter invisível, o BOM, que funciona como um carimbo a dizer «este texto está em UTF-8».

💾 Cópias de segurança

Lembras-te da aula 8? Os dados do CRM ficam no localStorage deste browser, neste computador. Se alguém limpar os dados do browser, se mudares de computador ou se o disco avariar… perdes tudo. Por isso vamos criar uma cópia de segurança (em inglês, backup): um ficheiro copia-crm.json com as 3 tabelas (clientes, interações e oportunidades), no formato JSON que já conheces. Com esse ficheiro, consegues restaurar tudo, neste ou noutro computador.

🏢 Nas empresas, as cópias de segurança são obrigatórias: fazem-se todos os dias e guardam-se noutro sítio (outro disco, a «nuvem»), para o caso de incêndio, roubo ou vírus. E o RGPD (Regulamento Geral sobre a Proteção de Dados) obriga as empresas a proteger os dados pessoais dos clientes — não os perder, mas também não os deixar cair em mãos erradas. Uma cópia com dados de clientes guarda-se em lugar seguro, não numa pen esquecida no autocarro!

🤔 Pensa: uma página web pode escrever ficheiros no teu disco sempre que quiser? Porque é que isso seria perigoso?

Parte B — Os botões e o código (≈ 20 min)

1 O link do menu

No index.html, dentro do <nav class="menu">, por baixo do comentário AULA 16: COLAR AQUI O LINK DOS RELATÓRIOS:

2 A secção dos relatórios (HTML)

Três botões. Os dois primeiros já conheces. O terceiro tem um truque: o <input type="file"> (que abre a janela para escolher um ficheiro) é feio, por isso o CSS esconde-o e mostra só o <label> com o aspeto de um botão. Clicar no <label> é o mesmo que clicar no <input> que está lá dentro. O accept=".json" faz a janela mostrar só ficheiros .json.

⚠️ Atenção ao sítio: este bloco vai para o comentário AULA 16: COLAR AQUI OS RELATÓRIOS, dentro do <main> (por baixo do painel) — não para o do menu.

🤔 Prevê: o que acontece se clicares agora em 📄 Exportar clientes (Excel)? Experimenta, com a Consola aberta.

✅ Deves ver: o cartão Relatórios e cópias de segurança com 3 botões. Ao clicar no primeiro aparece na Consola o erro exportarClientesCSV is not defined — é normal: a função ainda não existe.

3 As funções de exportar e restaurar (JavaScript)

No app.js, por baixo do comentário // ===== AULA 16: COLAR AQUI =====. Desta vez só há um comentário da aula 16 no app.js e não é preciso acrescentar nada a atualizarEcra(): os relatórios não se desenham no ecrã, só trabalham quando carregas num botão.

O que faz cada função:

⚠️ Atenção ao BOM: em exportarClientesCSV vais ver '\uFEFF' + csv. O \uFEFF é a forma de escrever o BOM (o tal carimbo invisível) em JavaScript. Não o apagues: sem ele, os acentos aparecem estragados no Excel. Se escreveres a linha à mão (por exemplo no E2), copia-o tal e qual: barra, u, FEFF.

✅ Deves ver: nenhum erro na Consola. Agora os três botões já fazem alguma coisa — vamos testá-los com calma na Parte C.

Parte C — Testar a sério: Excel, cópia e restauro (≈ 20 min)

4 Abrir o relatório no Excel

  1. Clica em 📄 Exportar clientes (Excel). O browser descarrega o ficheiro clientes.csv (normalmente vai para a pasta Transferências; para ver a lista das transferências do browser, carrega em Ctrl+J).
  2. Abre-o no Excel: duplo clique no ficheiro, ou, no Excel, Ficheiro → Abrir → Procurar e escolhe a pasta Transferências (se não o vires, escolhe «Todos os ficheiros» no tipo de ficheiro).
  3. Confirma: cada campo na sua coluna, o cabeçalho na linha 1, os acentos certos (João Gonçalves, Ribeirão) e as notas «Ligar às 10h; prefere email» numa só célula.

✅ Deves ver: uma folha de cálculo arrumada, com 8 colunas (Nome, Empresa, Email, Telefone, NIF, Estado, Criado em, Notas) e uma linha por cliente. Os telefones, os NIF e as datas podem aparecer alinhados à direita ou com outro formato (ex.: 15/09/2026): é o Excel a reconhecer números e datas — está tudo bem.

😕 Não foi descarregado nada
  • Olha para o canto superior direito do browser (ícone de transferências) ou carrega em Ctrl+J: o ficheiro pode estar lá e tu não reparaste.
  • O browser pode ter bloqueado a transferência ou estar à espera da tua autorização: procura uma mensagem como «Este site tentou transferir vários ficheiros» (clica em Permitir) ou um aviso na lista de transferências (escolhe Manter).
  • O Firefox pode perguntar o que fazer com o ficheiro: escolhe Guardar ficheiro.
  • Alguns computadores da escola não deixam transferir ficheiros: avisa o professor.
  • Abre a Consola: se aparecer exportarClientesCSV is not defined, o passo 3 não está no sítio certo ou não foi gravado.
😕 O Excel abre tudo numa só coluna (com os ; e as aspas à vista)

O teu Windows ou o teu Excel estão configurados para usar a vírgula como separador (acontece com o Excel em inglês). Não precisas de mudar o código:

  • Solução rápida: seleciona a coluna A → separador Dados → Texto para Colunas → Delimitado → Seguinte → marca Ponto e vírgula → Concluir.
  • Solução «profissional»: num livro novo, Dados → De Texto/CSV (nalgumas versões: Dados → Obter Dados → De Ficheiro → De Texto/CSV), escolhe o clientes.csv, confirma que o Delimitador é Ponto e vírgula e clica em Carregar.
😕 Os acentos aparecem estragados (João, Gonçalves) ou aparece  antes de «Nome»
  • Quase sempre é o BOM que se perdeu: escreveste a linha do descarregarFicheiro sem o '\uFEFF' +, ou apagaste-o. Volta a copiar a função exportarClientesCSV com o botão 📋 Copiar, grava e exporta outra vez.
  • Se mesmo assim não resultar (Excel muito antigo), importa com Dados → De Texto/CSV e, em Origem do Ficheiro, escolhe 65001: Unicode (UTF-8).
😕 Outros problemas com o Excel (ou não tenho Excel)
  • Aparece uma barra amarela «Vista Protegida»: é porque o ficheiro veio da Internet (do browser). Clica em Ativar Edição.
  • O ficheiro chama-se clientes (1).csv: o browser acrescenta um número quando já existe um ficheiro com o mesmo nome. É normal (o E2 resolve isto).
  • O Excel diz que o ficheiro está a ser usado: fecha o clientes.csv no Excel antes de exportares outra vez com o mesmo nome.
  • LibreOffice Calc: ao abrir aparece a janela Importar texto: em Conjunto de caracteres escolhe Unicode (UTF-8), em Opções de separador marca só Ponto e vírgula e clica em OK.
  • Google Sheets: Ficheiro → Importar → Carregar, escolhe o ficheiro e, em Tipo de separador, deixa Detetar automaticamente (ou escolhe Personalizado e escreve ;).
  • Mac: o duplo clique pode abrir no Numbers, que também serve; o Excel para Mac funciona como no Windows.

5 Fazer a cópia de segurança e espreitá-la

  1. Clica em 💾 Fazer cópia de segurança. O browser descarrega o ficheiro copia-crm.json.
  2. Abre-o no VS Code: Ficheiro → Abrir Ficheiro… e escolhe-o na pasta Transferências (ou arrasta o ficheiro para dentro da janela do VS Code).
  3. Não alteres nada neste ficheiro: basta faltar uma vírgula para deixar de ser um JSON válido.

✅ Deves ver: um texto arrumado, que começa por { e tem três listas: "clientes": [ … ], "interacoes": [ … ] e "oportunidades": [ … ], com todos os teus dados. É o CRM inteiro num só ficheiro!

💡 Se o ficheiro abrir no browser em vez do VS Code, não faz mal: dá para ver na mesma. Para o abrires no VS Code, botão direito no ficheiro → Abrir com → Visual Studio Code.

6 O grande teste: apagar tudo e restaurar

⚠️ Faz isto pela ordem certa! Só apagas os dados depois de teres confirmado, no passo 5, que o copia-crm.json tem os teus dados. Sem cópia, o que apagares perde-se para sempre.

  1. Abre o DevTools (F12) → Aplicação (Application) → Armazenamento local → o endereço do Live Server.
  2. Clica em crm_clientes e carrega na tecla Delete (ou botão direito → Eliminar). Faz o mesmo a crm_interacoes e a crm_oportunidades. Apaga só estas três.
  3. Carrega em F5: o CRM fica vazio — sem clientes, quadro vazio, painel a zeros. (Se fizeste o desafio da aula 8, aparecem os 3 clientes de exemplo: é normal.)
  4. Clica em 📂 Restaurar cópia, escolhe o copia-crm.json e responde OK à pergunta «Isto vai SUBSTITUIR todos os dados atuais. Continuar?».

✅ Deves ver: a mensagem «Cópia restaurada com sucesso!» e tudo de volta: clientes, interações (abre uma ficha!), oportunidades nas mesmas fases e o painel com os mesmos números. Carrega em F5: continua tudo lá, porque o restauro também gravou no browser.

😕 O restauro não funcionou
  • Aparece «Este ficheiro não é uma cópia válida do Mini-CRM.» → escolheste outro ficheiro (por exemplo o clientes.csv), ou o JSON foi alterado e ficou com um erro. Faz uma cópia nova.
  • Escolhes o ficheiro e não acontece nada → abre a Consola: importarCopia is not defined quer dizer que o passo 3 não está no sítio certo. (Se clicaste em Cancelar na pergunta, é normal não mudar nada.)
  • Não encontras o ficheiro na janela → procura na pasta Transferências; lembra-te de que a janela só mostra ficheiros .json.
  • Voltaram os clientes, mas faltam as oportunidades → a cópia foi feita antes de as criares. Abre o JSON no VS Code e confirma.
  • Apagaste os dados sem ter feito a cópia → infelizmente não há volta a dar: cria uns clientes novos e aprende a lição que as empresas aprendem da pior maneira. 😉

🔎 Investiga

  1. Abre o clientes.csv no Bloco de Notas (botão direito → Abrir com → Bloco de Notas) ou no VS Code. O que é cada linha? E a primeira? O que separa os valores? Vês as aspas?
  2. Cria um cliente com aspas no nome, por exemplo Pastelaria "O Doce", e exporta outra vez. Como aparece o nome no Bloco de Notas? E no Excel? Que função tratou disto? E o que acontecia às notas «Ligar às 10h; prefere email» se não houvesse aspas à volta das células?
  3. Para que serve uma cópia de segurança numa empresa? Escreve 3 situações em que uma cópia salvava a empresa. Onde guardarias a cópia do CRM? E onde é que nunca a deixarias, tendo em conta o RGPD?
  4. No copia-crm.json, procura uma interação. Tem o nome do cliente ou só o clienteId? Porque é que, depois de restaurar, cada interação continua a aparecer no cliente certo?

✍️ Exercícios (fazem parte do teu projeto)

Estes exercícios não têm o código pronto: usa as funções de hoje como modelo.

E1 · Exportar as oportunidades (com o nome do cliente)

Acrescenta um botão «📄 Exportar oportunidades (Excel)» na secção dos relatórios, que descarrega um ficheiro oportunidades.csv com as colunas Título; Cliente; Valor; Fase; Data prevista. Na coluna Cliente tem de aparecer o nome do cliente, e não o número do clienteId.

💡 Dica: copia a ideia de exportarClientesCSV para uma função nova. Para o nome, faz como no cartaoOportunidade da aula 14: procurarCliente(op.clienteId) (e cuidado se devolver null). Isto é juntar duas tabelas pela chave estrangeira — o JOIN da aula 11! Para o Excel português perceber o valor como número, troca o ponto pela vírgula: depois de toFixed(2), usa .replace('.', ',').

E2 · A data no nome do ficheiro

Faz com que o ficheiro dos clientes passe a chamar-se, por exemplo, clientes-2026-10-03.csv, com a data de hoje. Assim, quem exporta todas as semanas não fica com clientes (1).csv, clientes (2).csv…

💡 Dica: já usaste no CRM uma expressão que dá a data de hoje no formato AAAA-MM-DD — procura criadoEm em guardarCliente(). Guarda-a numa variável e junta os textos com + no primeiro valor do descarregarFicheiro(…).

⭐ Desafio · Relatório imprimível

Acrescenta um botão «🖨️ Imprimir relatório» que abre a janela de impressão do browser. Na impressão não devem aparecer o menu, os formulários, os filtros, os botões nem a secção dos relatórios — só as tabelas, o quadro e o painel.

💡 Dica: o JavaScript tem uma função pronta que abre a janela de imprimir: window.print(). No CSS, as regras escritas dentro de @media print { … } só se aplicam quando se imprime; lá dentro, display: none esconde o que não interessa. Para testar sem gastar papel, usa Ctrl+P e vê a pré-visualização (ou escolhe «Guardar como PDF»).

📦 O que mostrar ao professor

⏱️ Se sobrar tempo

🏁 A partir daqui, o CRM é teu

Acabou o código guiado! O teu Mini-CRM já faz o que fazem muitas aplicações de gestão a sério: guarda clientes, regista o histórico, acompanha negócios por fases, mostra indicadores, exporta relatórios e faz cópias de segurança. Nas próximas aulas vais adaptá-lo ao teu setor (aula 17), testá-lo e escrever o manual (aula 18), publicá-lo na Internet (aula 19) e apresentá-lo (aula 20).

🤖 Pedir ajuda à IA (opcional)

Se ficaste com dúvidas sobre CSV, codificação de caracteres ou cópias de segurança, pede a uma IA gratuita que te explique. Copia este pedido e cola-o na IA:

📖 Palavras novas

Relatório
Informação tirada da aplicação para ser lida, partilhada ou impressa (ex.: lista de clientes em Excel).
CSV
Ficheiro de texto com uma linha por registo e os valores separados por um separador (no nosso caso, ;).
Separador
O carácter que separa as colunas num CSV (vírgula ou ponto e vírgula).
UTF-8
A forma mais usada de guardar letras como números; inclui acentos, ç e emojis.
BOM
Carácter invisível no início de um ficheiro que avisa «este texto está em UTF-8».
Blob
Um «ficheiro na memória», criado pelo JavaScript, que se pode descarregar.
Transferência (download)
Guardar no computador um ficheiro que vem do browser ou da Internet.
Cópia de segurança (backup)
Cópia dos dados guardada noutro sítio, para os recuperar se se perderem.
Restaurar
Repor os dados a partir de uma cópia de segurança.
FileReader
Objeto do JavaScript que lê um ficheiro escolhido pelo utilizador.
try { … } catch { … }
«Tenta fazer isto; se der erro, apanha-o e faz aquilo» — evita que o programa pare.
RGPD
Regulamento Geral sobre a Proteção de Dados: regras europeias sobre como as empresas tratam e protegem os dados pessoais.