Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML.
Curso
Sistema de Biblioteca – Parte IV: Devoluções
Finalmente, nosso último cadastro! Depois de cadastrarmos os leitores, livros, e empréstimos de nossa biblioteca, resta-nos apenas cadastrara as devoluções dos livros. Esta parte do curso é mais simples do que as anteriores, pois não veremos nenhuma novidade, será apenas uma revisão do aprendizado anterior. Veremos aqui o formulário de devoluções e a consulta, indicando os leitores que estão com suas datas vencidas. Neste passo, não usaremos nosso modelo de cadastro (criado nas edições anteriores), pois este formulário terá uma interface um pouco diferente. Na figura 1 podemos visualizar o formulário de devoluções compilado:
Figura 1: Formulário de Devoluções
Como mostrado na figura, o formulário de devoluções possui alguns TComboBoxes na parte superior e um TDBGrid no meio do formulário. Repare que pela primeira vez em nosso sistema usaremos o controle TPageControl, aquele que faz as abas do Windows. Nas respectivas abas, iremos visualizar os empréstimos em aberto, os empréstimos fechados e, no último, os empréstimos que ultrapassaram a data de vencimento, que é de 15 dias após o empréstimo, conforme especificado na edição nº 1. Nos objetos TComboBoxes, o usuário poderá selecionar pelo cliente e selecionar a ordem no qual os dados serão exibidos. Dando um clique duplo sobre o item na grade, o usuário estará cadastrando uma devolução para aquele empréstimo, tornando-o OK. Então, anime-se, pois com este iremos finalizar nossos cadastros.
Começaremos criando o objeto TForm e configurando-o de acordo com a tabela abaixo:
Tabela 1: Objeto TForm | |
Name |
FrmDevolução |
BorderStyle |
bsDialog |
Position |
poScreenCenter |
Caption |
Devolução de Livros |
Salve o formulário e chame sua unidade de devolucao.pas. Abra o formulário FrmPrincipal, o form "pai" da aplicação, e crie um item de menu abaixo da opção Controle (criado na 1ª edição). Configure a propriedade Caption desse submenu para ‘Devoluções’. Em seu evento OnClick, digite:
procedure TFrmPrincipal.
Devolues1Click (Sender : TObject);
begin
FrmDevolucao.ShowModal;
end;
Salve o projeto e execute. O Delphi irá questionar a inclusão da chamada a esta unidade2. Basta responder Yes e prosseguir.
Com o formulário criado e configurado, vamos inserir os objetos necessários, de acordo com a figura 3. Configure-os de acordo com a lista abaixo:
Figura 3: segunda aba do TPageControl
Tabela 2: Objeto ComboBox1 | |
Name |
cboLeito |
Style |
csDropDownList |
Tabela 3: Ojeto ComboBox2 | |
Name |
cboOrdem |
Style |
csDropDownList |
Items |
Nome |
|
Data |
Tabela 4: Objeto Table1 | |
Name |
tbLeitor |
DtabaseName |
Biblio |
TableName |
Leitor.db |
IndexName |
IndNome |
Tabela 5: Objeto Table2 | |
Name |
tbEmprestimo |
DatabaseName |
Biblio |
TableName |
Emprestimo.db |
2
Tabela 6: Ojeto Query1 | |
Name |
qyEmpretimo |
DatabaseName |
Biblio |
Tabela 7: Objeto Query2 | |
Name |
qyLivrosEmp |
DatabaseName |
Biblio |
Tabela 8: Objeto DataSourcel | |
Name |
dsEmprestimo |
Dataset |
qyEmprestimo |
Tabela 9: Objeto DataSource2 | |
Name |
dsLivrosEmp |
Dataset |
qyLivrosEmp |
Tabela10: Objeto DBGrid | |
Name |
DBEmprestimo |
DataSource |
dsEmprestimo |
Tabela 11: Objeto DBGrid2 | |
Name |
DBLivrosEmp |
DataSource |
dsLivrosEmp |
Insira também um objeto TPageControl. Para criar as três abas morstradas na figura 3, clique com o botão direito do mouse sobre o objeto e selecione a opção New Page. Repare que dentro do objeto PageControl, existirão três objetos da classe TTabSheet, cada um em sua respectiva aba. Configura as propriedades dos objetos TabSheet de acordo com a lista abaixo: (Para selecionar o Tabsheet, clique dentro do corpo do PageControl)
Tabela 12: Objeto PageControl (aba 1) | |
Caption |
Empréstimos |
Tabela 13: Objeto PageControl (aba 2) | |
Caption |
Devoluções |
Tabela 14: Objeto PageControl (aba 3) | |
Caption |
Em Atraso |
Iniciaremos pelo evento mais simples, o clique no botão Fechar do formulário:
procedure TFrmDevolucoes.
btFecharClick (Sender:Tobject);
begin
close;
end;
O próximo passo será preencher o objeto cboLeitor com os respectivos nomes. O preenchimento deste ComboBox será feito de forma manual, percorrendo toda a tabela de leitores e preenchendo-a. Repare que a tabela está indexada pelo campo nome, conforme configurado anteriormente. No evento OnShow do Form, digite:
procedure TFrmDevolucoes.
FormShow (Sender: TObject);
begin
tbLeitor.Open;
cboLeitor.Itemsclear;
cboLeitor.Items.Add (‘Todos’);
while not tbLeitor.Eof do
begin
cboLeitor.ItemsAdd (
TbLeitor.Fieldbyname
(‘Nome’).asString);
tbLeitor.next;
end;
cboLeitor.ItemIndex: = 0;
cboOrdem.ItemIndex: = 0;
end;
Primeiramente, a tabela de leitores é aberta. Em seguida, limpa-se todos os itens do objeto cboLeitor, através do método clear da propriedade/objeto items. Antes de inserir os valores da tabela de leitores, é inserido o item ‘Todos’. Quando o usuário selecionar este item, será desconsiderado o filtro por leitor, e todos os empréstimos em aberto serão exibidos. Em seguida é feito um loop que percorre toda a tabela de leitores e preenche os respectivos valores do campo Nome no objeto cboLeitor. E por último, fora do loop, a propriedade ItemIndex dos objetos cboLeitor e cboOrdem são setadas para zero. Isto é feito porque, como a propriedade style desses objetos foram setadas para csDropDownList, a propriedade ItemIndex só pode ser alterada em tempo de execução.
Devemos então ativar os objetos de seleção para que passem a funcionar. Para isto, vamos criar algumas constantes, que servirão para armazenar o código SQL:
Const
Sql1 = ‘select Leitor.Nome, emprestimo.dataemp’;
Sql2 = ‘from leitor, emprestimo’;
Sql3: String = ‘where emprestimo.leitor = leitor.codigo and emprestimo.DataDevolucao is null’;
Sql4: String = ‘where emprestimo.leitor = leitor.codigo and emprestimo.DataDevolucao is not null’;
var
FrmDevolucoes:TFrmDevolucoes;
Implementation
A cláusula Const pode ser inserida antes da cláusula Var, da seção interface.
O filtro por cliente será executado quando o usuário selecionar algum item na lista. O código para o filtro será feito, então, no evento OnChange do objeto cboLeitor.
Vamos por partes: O filtro deve ser feito de acordo com duas situações: Quando o usuário selecionar a opção Todos (índice 0), todos os empréstimos em aberto serão executados. Caso contrário, somente os empréstimos do cliente selecionado serão exibidos. Vejamos a primeira situação:
procedure TFrmDevolucoes.
cboLeitorChange (Sender:TObject);
begin
qyDevolucao.Sql.clear;
qyDevolucao.Sql.Add (sql1);
qyDevolucao.Sql.Add (sql2);
qyDevolucao.sql.add (sql3);
if cboOrdem.ItemIndex = 0 then
qyDevolucao.Sql.Add (‘order
by leitor.nome’)
else
qyDevolucao.sql.add (‘order by emprestimo.dataemp’);
qyDevolucqo.Open;
end;
Primeiro, devemos limpar o conteúdo da propriedade SQL e atribuir o código SQL padrão:
qyDevolucao.Sql.Clear;
qyDevolucao.Sql.Add (Sql1);
qyDevolucao.Sql.Add (Sql2);
qyDevolucao.Sql.Add (Sql3);
Repare que a propriedade SQL, do objeto TQuery, é a que armazena o código SQL que será executado no momento da abertura da Query. A propriedade SQL é um objeto da classe Tstrings, e possui, portanto, métodos e propriedades para manipulação de seu conteúdo. O código descrito acima simplesmente limpa o conteúdo do código SQL e adiciona as três linhas básicas de nossa consulta, que foi armazenada nas constantes SQL1, SQL2 e SQL3. O último passo então é especificar em qual ordem os dados serão exibidos na grade. Esta ordem é executada de acordo com o objeto cboOrdem:
if cboOrdem.ItemIndex=0 then
qyDevolucao.Sql.Add (‘order
by leitor.nome’)
else
qyDevolucao.sql.add (‘order
by emprestimo.dataemp’);
O método Add sempre insere no final da lista, e portanto, adicionará a cláusula Order by após as três linhas padrões da consulta.
Ok! Basta apenas abrir a query no final da procedure:
qyDevolucao.Open;
Para criar o filtro da segunda situação, basta adicionar o código a seguir:
procedure TFrmDevolucoes.
cboLeitorChange (Sender:TObject);
begin
qyDevolucao.Sql.Clear;
qyDevolucao.Sql.Add (Sql1);
qyDevolucao.Sql.Add (Sql2);
qyDevolucao.Sql.Add (Sql3);
if cboLeitor.ItemIndex>0
then begin
TbLeitor.FindKey ( [
CboLeitor.Text] );
qyDevolucao.Sql.Add (‘and
leitor.codigo = ‘+
TbLeitor.Fieldbyname
(‘codigo’).asString);
end;
if cboOrdem.ItemIndex=0 then
qyDevolucao.Sql.Add (‘order
by leitor.nome’)
else
qyDevolucao.Sql.Add (‘order
by emprestimo.dataemp’);
qyDevolucao.Open;
end;
Repare que após a inclusão das três linhas básicas da query, é feita a comparação pra verificar se foi selecionado um cliente específico:
if cboLeitor.ItemIndex>0
then begin
Após, devemos capturar o código do leitor selecionado. Para isto, é executado o método FindKey, passando o nome do leitor selecionado como parâmetro. Lembre-se que a tabela está indexada pelo campo nome:
TbLeitor.FindKey ( [CboLeitor. Text] );
E após é adicionado o filtro SQL no objeto Tquery:
qyDevolucao.sql.add (‘and
leitor.codigo = ‘+
TbLeitor.Fieldbyname
(‘codigo’).asString);
Com isto, o filtro pelo cliente já pode ser executado pelo usuário. Com este código, podemos também ativar o objeto CboOrdem. Este comboBox permite que o usuário selecione em qual ordem os dados serão exibidos: pelo nome do leitor ou pela data do empréstimo. O evento usado também foi o onChange:
procedure TFrmDevolucoes.
cboOrdemChange (Sender: TObject);
begin
cboLeitorChange (nil);
end;
O que devemos fazer é apenas executar o evento OnChange do objeto cboLeitor, pois nele já é executado todo o código necessário para a seleção por leitor e a ordem de exibição.
O objeto DbLivrosEmprestados, da classe TdbGrid, exibirá os livros relacionados ao empréstimo selecionado no objeto DbEmprestimo. O objeto DbLivrosEmprestados está linkado com o query QyLivrosEmp. Este query deve ser utilizado sempre que o usuário selecionar um empréstimo diferente na grade. Podemos então, executar o filtro no evento onAfterScroll, do objeto QyEmprestimos:
procedure TFrmDevolucoes.
qyEmprestimoAfterScroll
(DataSet: TDataSet);
begin
qyLivrosEmp.Close;
qyLivrosEmp.Prepare;
qyLivrosEmp.Sql.Clear;
qylivrosEmp.Sql.Add (
‘SELECT livrosemp.serie,
livros.titulo’);
qyLivrosEmp.Sql.Add (
‘from livrosemp, livros’);
qyLivrosemp.Sql.Add (
‘where livrosemp.codLivro
=Livros.Codigo’);
qyLivrosEmp.Sql.Add (‘and
livrosemp.CodEmp = ‘+
qyEmprestimo.Fieldbyname
(‘Codigo’).asString);
qyLivrosEmp.Open;
end;
Vamos nos ater a cláusula SQL:
Select LivrosEmp.Serie,
Livros.Titulo
From LirosEmp, Livros
Where LivrosEmp.Codlivro =
Livros.Codigo
And LivrosEmp.CodEmp = XXX
O que é feito é uma união entre as tabelas LivrosEmp e Livros. A tabela de livros é inserida no SQL apenas para que seja exibido o título do livro na grade. E a linha:
And livrosEMp.CodEmp =
(QyEmprestimo.Fieldbyname
(‘Codigo’).asString)
Seleciona apenas os livros relacionados aos empréstimo atualmente selecionado no objeto QyEmprestimo.
Com este código, sempre que o usuário navegar no objeto dbEmprestimo, o objeto QyLivrosEmp será atualizado, exibindo assim, somente os livros referentes ao empréstimo atual.
Podemos refinar um pouco mais este código, inserindo as linhas abaixo:
procedure TFrmDevolucoes.
qyEmprestimoAfterScroll
(DataSet: TDataSet);
begin
if qyEmprestimo.Fieldbyname
(‘Codigo’).asString<>’’
then begin
qyLivrosEmp.Close;
qyLivrosEmp.Prepare;
qyLivrosEmp.Sql.Clear;
qyLivrosEmp.Sql.Add (
‘SELECT livrosemp.serie,
livros.titulo’);
qyLivrosEmp.Sql.Add (
‘from livrosemp, livros’);
qyLivrosemp.Sql.Add (
‘where livrosemp.codLivro
=Livros.Codigo’);
qyLivrosEmp.Sql.Add (‘and
livrosemp.CodEmp = ‘+
qyEmpretimo.Fieldbyname
(‘Codigo’).asString);
qyLivrosEmp.Open;
end;
Vamos nos ater a cláusula SQL:
Select LivorsEmp.Serie,
Livros.Titulo
From LivrosEmp, Livros
Where LivrosEmp.Codlivro =
Livros.Codigo
And LivrosEmp.CodEmp = XXX
O que é feito é uma união entre as tabelas LivrosEmp e Livros. A tabela de livros é inserida no SQL apenas para que seja exibido o título do livro na grade. E a linha:
And livrosEmp.CodEmp =
(QyEmprestimo.Fieldbyname
(‘Codigo’).asString)
Seleciona apenas os livros relacionados ao empréstimo atualmente selecionado no objeto QyEmprestimo.
Com este código, sempre que o usuário navegar no objeto dbEmprestimo, o objeto QyLivrosEmp será atualizado, exibindo assim, somente os livros referentes ao empréstimo atual.
Podemos refinar um pouco mais este código, inserindo as linhas abaixo:
procedure TFrmDevolucoes.
qyEmprestimoAfterScroll
(DataSet: TDataSet);
begin
if qyEmprestimo.Fieldbyname
(‘Codigo’).asString<>’’
then begin
qyLivrosEmp.Close;
qyLivrosEmp.Prepare;
qyLivrosEmp.Sql.Clear;
qylivrosEmp.Sql.Add
(‘Select livrosemp.serie,
livros.titulo’);
qyLivrosEmp.Sql.Add (‘from
livrosemp, livros’);
qyLivorsemp.Sql.Add (‘where
livorsemp.codLivro =
Livros.Codigo’);
qyLivrosEmp.Sql.Add (‘and
QyEmpretimo.Fieldbyname
(‘Codigo’).asString);
qyLivrosEmp.Open;
end
else
qyLivrosEmp.Close;
end;
Isto irá garantir que o sistema não falhe quando o usuário selecionar um leitor que não possua empréstimos.
Ok! A primeira Aba já está funcional. Devemos agora criar a funcionalidade da Segunda aba, cujo objetivo é exibir todos os empréstimos que já foram devolvidos. Primeiramente, a aba deve ser preenchida com os dois objetos TdbGrid correspondentes, conforme mostra a figura 3.
Coloque os dois objetos DbGrid, conforme a descrição abaixo:
Tabela 15: Objeto DBGrid3 | |
Name |
DBDevolucao |
DataSource |
dsEmprestimo |
Tabela 16: Objeto DBGrid4 | |
Name |
DBLivrosDev |
DataSource |
dsLivrosEmp |
E para exibir somente os empréstimos já fechados, basta inserir a cláusula abaixo no evento onchange do objeto CboLeitor:
procedure TFrmDevolucoes.
cboLeitorChange (Sender:TObject);
var
data: TDateTime;
begin
qyEmprestimo.Sql.Clear;
qyEmprestimo.Sql.Add (Sql1);
qyEmprestimo.Sql.Add (Sql2);
if PageControl1.ActivePage=
TabSheet2 then
qyEmprestimo.Sql.add (Sql4);
else
qyEmprestimo.Sql.add (Sql3);
if cboLeitor.ItemIndex>0
then begin
tbLeitor.FindKey ( [
CboLeitor.Text] );
qyEmprestimo.Sql.add (‘ and
leitor.codigo = ‘ +
TbLeitor.Fieldbyname
(‘codigo’).asString);
end;
if cboOrdem.ItemIndex=0 then
qyEmprestimo.Sql.Add (‘order
by leitor.nome’)
else
qyEmprestimo.Sql.Add (‘order
by emprestimo.dataemp’);
qyEmprestimo.Open;
end;
Repare que a cláusula anterior:
QyEmprestimo.Sql.Add (SQl3);
Foi substituída por:
if PageControl1.ActivePage =
TabSheet2 then
qyEmprestimo.Sql.Add (Sql4)
else
qyEmprestimo.Sql.Add (Sql3);
A variável sql4 já contém a cláusula Where referente a exibição dos Empréstimos Fechados:
‘where emprestimo.leitor =
leitor.codigo and
emprestimo.DataDevolucao is
not null’;
O que deve ser feito é uma comparação para saber se a aba selecionada foi a Segunda. Esta comparação é feita através da propriedade ActivePage, do objeto Pagecontrol, que representa nossas abas:
if PageControl1.ActivePage=
TabSheet2 then
E no evento OnChange do objeto PageControl, devemos atualizar query, para que este reflita o novo filtro selecionado:
procedure TFrmDevolucoes.
PageControl1Change (Sender:
TObject);
begin
cboLeitorChange (nil);
end;
Simples – basta chamar o evento onchange do objeto cboLeitor, conforme feito anteriormente no objeto cboOrdem. Com isto, a segunda aba tem sua funcionalidade terminada. Vamos agora criar a terceira aba, que tem como objetivo exibir somente os empréstimos em atraso, conforme mostra a figura 4.
Insira os dois objetos DbGrid no formulário e configure suas respectivas propriedades de acordo com a descrição abaixo:
Tabela 17: Objeto DBGrid5 | |
Name |
DBEmAtraso |
DataSource |
dsEmprestimo |
Tabela 18: Objeto DBGrid6 | |
Name |
DBLivrosEmAtraso |
DataSource |
dsLivrosEmp |
Para exibir os empréstimos em atraso, basta incluir a cláusula abaixo no evento OnChange do objeto cboLeitor:
procedure TFrmDevolucoes.
cboLeitorChange (Sender:TObject);
var
data:TDateTime;
begin
qyEmprestimo.Sql.Clear;
qyEmprestimo.Sql.Add (Sql1);
qyEmprestimo.Sql.Add (Sql2);
if PageControl1.ActivePage=
TabSheet2 then
qyEmprestimo.Sql.Add (Sql4);
else
qyEmprestimo.Sql.Add (Sql3);
if cboLeitor.ItemIndex>0
then begin
TbLeitor.FindKey
( [CboLeitor.Text] );
qyEmprestimo.Sql.add (‘ and
leitor.codigo = ‘ +
TbLeitor.Fieldbyname
(‘codigo’).asString);
end;
if PageControl1.ActivePage=
TabSheet3 then
qyEmprestimo.Sql.Add (‘ and
" ‘ + FormatDateTime
(‘mm/dd/yyyy’, now) + ‘"
– DataEmp > 15’);
if cboOrdem.ItemIndex=0
then
qyEmprestimo.Sql.Add (‘order
by leitor.nome’)
else
qyEmprestimo.sql.add (‘order
by emprestimo.dataemp’);
qyEmprestimo.Open;
end;
Primeiro, é verificado se a aba atual é a terceira, através da propriedade ActivePage, do objeto PageControl:
if PageControl1.ActivePage =
Tabsheet3 then
Caso verdadeiro, é adicionado a cláusula SQL que retorna os empréstimos vencidos:
qyEmprestimo.Sql.Add (‘ and
" ‘ + FormatDateTime
(‘mm/dd/yyyy’, now) + ‘ "
– DataEmp > 15’)
Figura 4: Terceira aba do TPageControl
O filtro é feito baseado no período de 15 dias de vencimento, conforme especificado na edição nº 1. O que é feito é simplesmente a subtração da data atual com o campo DataEmp, que representa a data de empréstimo. Para retornar a data atual, foi usada a função FormatDateTime:
FormateDateTime
(‘mm/dd/yyyy’, now)
A função FormatDateTime converte um valor do tipo DateTime para String. O primeiro parâmetro especifica qual será o formato da datas, que no caso, deve ser passado ao SQL como mês/dia/ano.
E com isto, as três abas passam a exibir corretamente seus respectivos conteúdos, assim como aceitam o uso dos filtros relacionados. O último retoque necessário é a chamada ao método cboLeitorChange no evento onShow do formulário, para que este inicie exibindo os dados corretamente:
procedure TFrmDevolucoes.
FormShow (Sender: TObject);
begin
tbLeitor.Open;
tbLeitor.First;
cboLeitor.Items.clear;
cboLeitor.Items.Add (‘TODOS’);
while not tbLeitor.Eof do
begin
cboLeitor.Items.Add (
TbLeitor.Fieldbyname
(‘Nome’).asString);
tbLeitor.next;
end;
cboLeitor.ItemIndex: = 0;
cboOrdem.ItemIndex: = 0;
cboLeitorChange (nil);
end;
O que deve ser feito agora é o cadastramento das devoluções. O usuário fará o registro de devolução de uma forma bem simples: dando um clique duplo sobre o empréstimo referente. No evento ondblClick do objeto DbGrid, o sistema exibirá uma caixa de diálogo pedindo a confirmação da entrega. Caso a resposta seja positiva, será gravado a data de devolução do empréstimo na tabela.
Coloque um objeto Ttable, para que possamos inserir a data de devolução na tabela de empréstimos.
NOTA: O objeto Tquery possui a propriedade RequestLive, que permite o uso de /inserções/alterações através da própria consulta. Esta propriedade está intimamente ligada ao tipo de query que é retornada pelo código SQL. No nosso caso, o SQL retorna uma query readonly, inviabilizando, portanto, o uso da propriedade requestlive. Veja a seguir as possíveis situações que fazem uma query se tornar do tipo read-only:
• Se alguma operação com o operador LIKE estiver sendo usada;
• Se existir a união de tabelas;
• O uso de cláusulas como JOIN ou UNION;
• O usuário não possuir permissões de alteração da tabela correspondente;
Vamos então configurar nosso objeto TTable, para que aponte para a tabela de empréstimos:
Tabela 19: Objeto Table1 | |
Name |
tbEmprestimo |
DatabaseName |
Biblio |
TableName |
Emprestimo.db |
E vamos ao evento onDblClick do objeto dbEmprestimos:
procedure TFrmDevolucoes.
DBEmprestimosDblClick (Sender:
TObject);
begin
if QyEmprestimo.
RecordCount = 0 then exit;
if application.MessageBox
(‘Confirma devolução?’,
‘Clube Delphi’, mb_YesNo)
= IdYes then begin
tbEmprestimo.FindKey
( [QyEmprestimo.fieldbyname
(‘Codigo’).asInteger] );
tbEmprestimo.Edit;
tbEmprestimo.Fieldbyname
(‘dataDevolucao’).
asDateTime: =now;
tbEmprestimo.Post;
cboLeitorChange (nil);
end;
end;
Aqui não há novidades: caso o usuário confirme a devolução dos livros, o sistema localiza o registro referente a tabela de empréstimos e preenche o campo DataDevolucao com a data atual. Por último, o evento onchange do objeto cboLeitor é chamado, para que haja um referesh das informações na tela. Repare que é feita uma verificação na quantidade de registros retornados pelo objeto QyEmprestimos na linha:
if QyEmprestimo.
RecordCount = 0 then exit;
Que impede o usuário de tentar cadastrar uma devolução sem que haja empréstimos. E para finalizar, abra a tabela no evento Onshow do form.
Conclusão
Este formulário, por ser o último cadastro, foi previsivelmente mais simples do que os anteriores. É claro que em uma situação bibliotecária real, seriam exigidos uma quantidade maior de informações. Mas isso fica a cargo de vocês, desenvolvedores, o incremento da funcionalidade do programa. Um exercício interessante seria a possibilidade de filtrar também pela data do empréstimo ou pela data da devolução. Explanar sobre todas essas possibilidades seria redundante para o objetivo do curso.
Acredito que neste estágio o leitor já esteja apto a montar seus próprios cadastros, bastando usar apenas a imaginação, já que as ferramentas e métodos básicos já foram expostos durante nossas quatro edições. Nosso próximo passo será o refinamento da aplicação, criando as validações de integridade e o início da criação dos relatórios de nosso sistema.
Espero que tenham gostado e que este pequeno sistema tenha ajudado no aprendizado em Delphi!