Usando Delphi para criar um software de gestão de documentos - Parte 1 de ?
Tags: delphi, programming, tooling, productivity
Published: 2023-11-22 03:58:06

Criando o MVP do software atualmente chamado Prontuário Digital utilizado para gerir os documentos digitais dos alunos de uma escola.

Bom, esse tutorial/artigo é mais um complemento da história original do que um artigo em si, mas me acompanhe na criação dessa ferramenta que me auxiliou no processo de gestão dos documentos digitais dos alunos de uma escola de ensino médio.

O software foi desenvolvido no Delphi CM 10.4, e claro que também pode ser adaptado e utilizado para outros tipos de documentos, esteja a vontade.

O problema inicial foi apresentado em outro artigo (Link em breve), mas em resumo, precisava de uma ferramenta para auxiliar a distribuição e renomeação de centenas de arquivos PDFs, para alguns nomes mais comuns e distribuí-los nas suas pastas correspondentes.

---

O objetivo inicial é ter acesso aos arquivos PDF, que geralmente estariam em um pendrive ou outra pasta aleatória do computador, e seus conteúdos. 

Hora da mão na massa…

1. Em uma aplicação nova no Delphi, jogue no form 2 panels, um splitter e um edgebrowser. Alinhe-os horizontalmente, com os panels a esquerda e o edgebrowser, que servirá para visualizar os arquivos, alinhado como "Client".

2. No primeiro panel, faremos a navegação até encontrar nossos arquivos, jogue nele um DriveComboBox, um DirectoryListBox e um splitter, todos alinhados ao topo e um FileListBox alinhado como Client.

3. No segundo panel, coloque um ButtonGroup, alinhado como Client.

Você terá algo parecido com isso ao final:

![Aparência Inicial do Projeto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5csblbqbedps5f0tq82.png)

---

Vamos programar um pouco agora, interligando os componentes de navegação entre arquivos.

1. no evento OnChange do DriveComboBox, coloque:
```pascal
procedure TForm1.DriveComboBox1Change(Sender: TObject);
begin
  DirectoryListBox1.Drive := DriveComboBox1.Drive;
end;
```

2. no evento OnChange do DirectoryListBox, coloque:

```pascal
procedure TForm1.DirectoryListBox1Change(Sender: TObject);
begin
  FileListBox1.Directory := DirectoryListBox1.Directory;
end;
```

3. No FileListBox, caso precise, coloque um filtro dos tipos de arquivo que deseja utilizando a propriedade Mask (no meu caso, *.pdf), e adicione o seguinte código ao evento OnChange:

```pascal
procedure TForm1.FileListBox1Change(Sender: TObject);
begin
  EdgeBrowser1.Navigate('file://' + FileListBox1.FileName);
end;
```

> Nota: Para que o EdgeBrowser funcione corretamente, você precisa da DLL na pasta do seu exe. Você pode consegui-la diretamente pelo NuGet, neste link [https://nuget.info/packages/Microsoft.Web.WebView2/](https://nuget.info/packages/Microsoft.Web.WebView2/)

E pronto, em 5 minutos, já temos um visualizador de PDFs, que utiliza o Chomium do navegador Edge, uma solução simples para o ambiente windows. De brinde pelo Edge você ainda consegue salvar uma cópia e imprimir, sem nenhum código extra

![Opa, navegação ok e PDF abrindo.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5sxf7eqkygwuu98ttgf.png)

---

Próximo ponto… os documentos que tinhamos em mãos eram todos nomeados como "scanneddocument_0385395839.pdf", então o objetivo de visualizar o documento é identificar seu conteúdo para aí então renomeá-lo… agora entra ação o nosso segundo painel, com o buttongroup, que irá fazer essa tarefa por nós.

Vamos começar facilitando a leitura dos botões do ButtonGroup, aumentando o tamanho dos botões, então defina a propriedade gboFullSize presente em ButtonOptions para True.

Agora vamos criar uma procedure que adicionará botões dinamicamente no nosso ButtonGroup, vou chama-la de AdicionarBotaoNoBG, com um parametro string Caption:

```pascal
procedure TForm1.AdicionarBotaoNoBG(const Caption: String);
begin
  if Caption.Trim.Length > 0 then begin
    ButtonGroup1.Items.Add();
    ButtonGroup1.Items[ButtonGroup1.Items.Count-1].Caption := Caption;
  end;
end;
```

Agora vamos programar 2 botões de ação para a nossa ButtonGroup. Adicione 2 botões no nosso panel2 e alinhe-os como Bottom. Renomeie o 1º botão como AdicionarNome coloque seu caption como "Adicionar Nome" e no seu método OnClick adicione:

```pascal
procedure TForm1.AdicionarNomeClick(Sender: TObject);
begin
  AdicionarBotaoNoBG(InputBox('Adicionar Nome', 'Digite o Nome que será adicionado', ''));
end;
```

No segundo botão, colocamos o nome RemoverNome, seu caption como "Remover Nome" e no seu método OnClick teremos:

```pascal
procedure TForm1.RemoverNomeClick(Sender: TObject);
var
  botao: string;
  cont: integer;
begin
  botao := InputBox('Remover Nome', 'Digite o Nome que será removido', '');
  for cont := 0 to ButtonGroup1.Items.Count-1 do begin
    if ButtonGroup1.Items[cont].Caption = botao then begin
      ButtonGroup1.Items.Delete(cont);
      Break;
    end;
  end;   
end;
```

Então fazemos o ButtonGroup renomear os arquivos conforme clicamos em algum botão dele. No evento OnButtonClicked do seu ButtonGroup coloque:

```pascal
procedure TForm1.ButtonGroup1ButtonClicked(Sender: TObject; Index: Integer);
begin
  if FileListBox1.ItemIndex < 0 then
    Abort;
    
  if RenameFile(FileListBox1.FileName, ExtractFilePath(FileListBox1.FileName) + ButtonGroup1.Items[Index].Caption + '.pdf') then begin
    ShowMessage('OK!');
    FileListBox1.Update;
  end else
    ShowMessage('Ops!');

end;
```

Estamos verificando se há algum arquivo selecionado na FileListBox, e caso tenha, utilizamos a função RenameFile para renomeá-lo. Extraimos o local do arquivo e concatenamos com o caption do botão e a extensão ".pdf" para gerar o nome do arquivo. Por fim avisamos nosso usuário se tudo está certo ou não e também, caso positivo, atualizamos o FileListBox com seu novo nome.

---

![Aparência final do aplicativo deste artigo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qejbxuccwj4rez5nu4jr.png)

Tudo pronto e funcionando, para finalizar iremos apenas adicionar uma funcionalidade que irá persistir os nomes que formos adicionando ao ButtonGroup e também carregá-los ao iniciar o programa. 
Vamos criar uma procedure "SalvarButtonGroup":

```pascal
procedure TForm1.SalvarButtonGroup;
var
  Nomes: TStringList;
  i: Integer;
begin
  if ButtonGroup1.Items.Count > 0 then begin
    Nomes := TStringList.Create;
    for i := 0 to ButtonGroup1.Items.Count-1 do
      Nomes.Add(ButtonGroup1.Items[i].Caption);
    Nomes.SaveToFile(ExtractFilePath(ParamStr(0)) + 'nomes.data');
    Nomes.Free;
  end;
end;
```

Aqui percorremos a lista de botões do ButtonGroup e para cada um adicionamos sua caption na StringList. Ao final, salvamos essa lista em um arquivo chamado nomes.data que ficará na mesma pasta do software. Iremos fazer a chamada dessa função no evento FormClose do form principal:

```pascal
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SalvarButtonGroup;
end;
```

E por fim, a procedure "CarregarButtonGroup", que carrega a lista de nomes que criamos anteriormente:

```pascal
procedure TForm1.CarregarButtonGroup;
var
  Nomes: TStringList;
  i: Integer;
begin
  if FileExists(ExtractFilePath(ParamStr(0)) + 'nomes.data') then begin
    Nomes := TStringList.Create;
    Nomes.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'nomes.data');
    for i := 0 to Nomes.Count-1 do begin
      AdicionarBotaoNoBG(Nomes.Strings[i]);
    end;
    Nomes.Free;      
  end;         
end;
```

Estamos verificando se o arquivo nomes.data está presente na mesma pasta. Caso positivo, carregamos ele e para cada entrada, um botão será criado no ButtonGroup. Adicionaremos ela no evento FormCreate do form principal:

```pascal
procedure TForm1.FormCreate(Sender: TObject);
begin
  CarregarButtonGroup;
end;
```

---

MVP pronto para uso, conseguimos agilizar um trabalho manual que levaria semanas para poucos dias utilizando este aplicativo. Num próximo artigo, iremos adicionar a funcionalidade de Renomear pastas baseado em uma busca em banco de dados e move-las para o local desejado. 

Quando terminei o aplicativo em si, o que desenvolvemos aqui se tornou mais como uma ferramenta do que o "gestor" de documentos em si, porém foi o pontapé inicial que era necessário para entender o processo que seria necessário para gerir os documentos.

O código fonte desse projeto pode ser encontrado aqui: [https://github.com/andcarpi/delphi-pdf-viewer-renamer](https://github.com/andcarpi/delphi-pdf-viewer-renamer)