Criando um TTable em "runtime", definindo o tipo dos campos numéricos conforme a tabela.
Segue um fragmento da rotina de criação, em "runtime", de um componente TTable com
tipos de campos variados.
A motivação para isso é:
- Tendo um programa para edição de uma tabela de inventário, é preciso que este programa
abra tabelas de diferentes gerenciadores; as tabelas tem, em comum, determinados campos,
necessários para se fazer um inventário: codigointerno, codigoean, descricao, unidade,
custoun, saldo;
- Uma vez que as tabelas podem ser diferentes (MySQL, Paradox, FoxPro ou VisualdBase7),
os campos numericos são diferentes (tFloat ou tBCD)... e como há um campo calculado (no
caso, o valor do produto = custoun X saldo), é preciso definir no dataset da tabela os
campos que serão utilizados;
- Como não conseguia "redefinir" os tipos dos campos que geravam problema (custoun e saldo),
utilizava quatro componentes TTable distintos, um para cada tipo de gerenciador;
- Para eliminar estes componentes, a solução foi criar um único TTable, em "runtime",
com os campos necessários...
Como o código todo é muito extenso, coloquei somente as partes mais importantes...
Nome do form: formInveEdit ("formulário para Edição de Inventário")
//
Procedure TformInveEdit.FormCreate(Sender: TObject);
Begin
// Criar o componente TTable aqui, ao criar o form
Invent := TTable.Create(Application);
InventDS.DataSet := Invent;
Invent.OnCalcFields := InventCalcFields;
End;
Procedure TformInveEdit.InventCalcFields(DataSet: TDataSet);
Begin
// Este evento "calcula" o valor de cada item, multiplicando o custo unitário pela quantidade
// do produto.
With Invent do Begin
Try
FieldByName('valor').AsFloat :=
FieldByName('custoun').AsFloat*
FieldByName('saldo').AsFloat;
Except
FieldByName('valor').AsFloat := 0;
End;
End;{With Invent}
End;
Procedure TformInveEdit.AbrirButtonClick(Sender: TObject); // Botão para Abrir/Fechar a Tabela
Var
MyFieldCustoUnBCD, MyFieldSaldoBCD: TBCDField;
MyFieldValor, MyFieldCustoFloat, MyFieldSaldoFloat: TFloatField;
MyFieldDescricao: TStringField;
Begin
sTable := sTableEdit.Text;
If AbrirButton.Caption = '&Abrir' then
Begin
If Invent.Active then
Invent.Close;
{EndIf}
AbrirButton.Caption := 'Fechar';
Invent.TableName := sTable+IIF(bMySQLUse,'','.dbf');
// ********** Só consigo definir os campos na primeira vez que acesso a tabela.
// Do contrário, teria que "destruir" o componente e criá-lo de
// novo.
If bFirstOpen then
Begin
// ********************** Definições dos campos. Início.
// Primeiro, o campo "calculado", valor, sempre "tFloat".
Invent.FieldDefs.Clear;
MyFieldValorFloat := TFloatField.Create(Invent); // .Create(Invent);
With MyFieldValorFloat do Begin
FieldName := 'valor';
Calculated := True;
DataSet := Invent;
Name := 'Invent'+'valor';
DisplayFormat := '0.00';
Invent.FieldDefs.Add(Name, ftFloat, 0, false);
Invent.FieldDefs.Update;
End;
MyFieldDescricao := TStringField.Create(Invent);
With MyFieldDescricao do Begin
FieldName := 'descricao';
Calculated := False;
DataSet := Invent;
Size := 6;
Name := 'Invent'+'descricao';
Invent.FieldDefs.Add(Name, ftString, 06, false);
End;
If bMySQLUse or bIsParadox then
// Se quero abrir uma tabela de inventário feita no Paradox ou MySQL, criar
// campos de saldo e custo unitário como tFloat
Begin
MyFieldCustoUnFloat := TFloatField.Create(Invent);
With MyFieldCustoUnFloat do Begin
FieldName := 'custoun';
Calculated := False;
DataSet := Invent;
Name := 'Invent'+'custoun';
Precision := 0;
Size := 0;
// sFormatoCusto depende de cada empresa;
// Numa fabrica de raçoes, onde o custo unitário tem até quatro casas decimais,
// é "0.0000"; num comércio comu, é "0.00"
DisplayFormat := sFormatoCusto;
EditFormat := sFormatoCusto;
Invent.FieldDefs.Add(Name, ftFloat, 0, false);
End;
// Se tabela pelo MySQL, usar TFloat ********** Início ********
MyFieldSaldoFloat := TFloatField.Create(Invent);
With MyFieldSaldoFloat do Begin
FieldName := 'saldo';
Calculated := False;
DataSet := Invent;
Name := 'Invent'+'saldo';
Precision := 0;
Size := 0;
// sFormatoEstoque depende de cada empresa;
// Numa loja que não tem estoque fracionado, será "0" e numa loja que tem
// estoque fracionado (agropecuária por exemplo), pode ser "0.000"
DisplayFormat := sFormatoEstoque;
EditFormat := sFormatoEstoque;
Invent.FieldDefs.Add(Name, ftFloat, 0, false);
End;{With MyFieldEstestaFloat}
// Se tabela pelo MySQL ou Paradox, usar TFloat ********** Fim ********
End
Else
Begin
// Se tabela ttDbase ou ttFoxPro, usar TBCD ********** Início ********
MyFieldCustoUnBCD := TBCDField.Create(Invent);
With MyFieldCustoUnBCD do Begin
FieldName := 'custoun';
Calculated := False;
DataSet := Invent;
Name := 'Invent'+'custoun';
Precision := 0;
Size := 4;
// sFormatoCusto depende de cada empresa;
// Numa fabrica de raçoes, onde o custo unitário tem até quatro casas decimais,
// é "0.0000"; num comércio comu, é "0.00"
DisplayFormat := sFormatoCusto;
EditFormat := sFormatoCusto;
Invent.FieldDefs.Add(Name, ftBCD, 4, false);
End;
MyFieldSaldoBCD := TBCDField.Create(Invent);
With MyFieldSaldoBCD do Begin
FieldName := 'saldo';
Calculated := False;
DataSet := Invent;
Name := 'Invent'+'saldo';
Precision := 0;
Size := 3;
// sFormatoEstoque depende de cada empresa;
// Numa loja que não tem estoque fracionado, será "0" e numa loja que tem
// estoque fracionado (agropecuária por exemplo), pode ser "0.000"
DisplayFormat := sFormatoEstoque;
EditFormat := sFormatoEstoque;
Invent.FieldDefs.Add(Name, ftBCD, 3, false);
End;{With MyFieldEstestaBCD}
// Se tabela ttDbase, usar TBCD ********** Fim ********
End;
{EndIf}
// ********************** Definições dos campos. Final.
End;
{EndIf bFirstOpen then
bFirstOpen := False;
Invent.Open;
Invent.First;
StatusBar1.SimpleText := IntToStr(Invent.RecNo)+'/'+IntToStr(Invent.RecordCount);
End
Else
Begin
Invent.Close;
StatusBar1.SimpleText := '0/0';
AbrirButton.Caption := '&Abrir';
End;
{EndIf}
..
..
..
Pergunta
paulobergo
Criando um TTable em "runtime", definindo o tipo dos campos numéricos conforme a tabela.
Segue um fragmento da rotina de criação, em "runtime", de um componente TTable com
tipos de campos variados.
A motivação para isso é:
- Tendo um programa para edição de uma tabela de inventário, é preciso que este programa
abra tabelas de diferentes gerenciadores; as tabelas tem, em comum, determinados campos,
necessários para se fazer um inventário: codigointerno, codigoean, descricao, unidade,
custoun, saldo;
- Uma vez que as tabelas podem ser diferentes (MySQL, Paradox, FoxPro ou VisualdBase7),
os campos numericos são diferentes (tFloat ou tBCD)... e como há um campo calculado (no
caso, o valor do produto = custoun X saldo), é preciso definir no dataset da tabela os
campos que serão utilizados;
- Como não conseguia "redefinir" os tipos dos campos que geravam problema (custoun e saldo),
utilizava quatro componentes TTable distintos, um para cada tipo de gerenciador;
- Para eliminar estes componentes, a solução foi criar um único TTable, em "runtime",
com os campos necessários...
Como o código todo é muito extenso, coloquei somente as partes mais importantes...
Nome do form: formInveEdit ("formulário para Edição de Inventário")
//
Procedure TformInveEdit.FormCreate(Sender: TObject); Begin // Criar o componente TTable aqui, ao criar o form Invent := TTable.Create(Application); InventDS.DataSet := Invent; Invent.OnCalcFields := InventCalcFields; End; Procedure TformInveEdit.InventCalcFields(DataSet: TDataSet); Begin // Este evento "calcula" o valor de cada item, multiplicando o custo unitário pela quantidade // do produto. With Invent do Begin Try FieldByName('valor').AsFloat := FieldByName('custoun').AsFloat* FieldByName('saldo').AsFloat; Except FieldByName('valor').AsFloat := 0; End; End;{With Invent} End; Procedure TformInveEdit.AbrirButtonClick(Sender: TObject); // Botão para Abrir/Fechar a Tabela Var MyFieldCustoUnBCD, MyFieldSaldoBCD: TBCDField; MyFieldValor, MyFieldCustoFloat, MyFieldSaldoFloat: TFloatField; MyFieldDescricao: TStringField; Begin sTable := sTableEdit.Text; If AbrirButton.Caption = '&Abrir' then Begin If Invent.Active then Invent.Close; {EndIf} AbrirButton.Caption := 'Fechar'; Invent.TableName := sTable+IIF(bMySQLUse,'','.dbf'); // ********** Só consigo definir os campos na primeira vez que acesso a tabela. // Do contrário, teria que "destruir" o componente e criá-lo de // novo. If bFirstOpen then Begin // ********************** Definições dos campos. Início. // Primeiro, o campo "calculado", valor, sempre "tFloat". Invent.FieldDefs.Clear; MyFieldValorFloat := TFloatField.Create(Invent); // .Create(Invent); With MyFieldValorFloat do Begin FieldName := 'valor'; Calculated := True; DataSet := Invent; Name := 'Invent'+'valor'; DisplayFormat := '0.00'; Invent.FieldDefs.Add(Name, ftFloat, 0, false); Invent.FieldDefs.Update; End; MyFieldDescricao := TStringField.Create(Invent); With MyFieldDescricao do Begin FieldName := 'descricao'; Calculated := False; DataSet := Invent; Size := 6; Name := 'Invent'+'descricao'; Invent.FieldDefs.Add(Name, ftString, 06, false); End; If bMySQLUse or bIsParadox then // Se quero abrir uma tabela de inventário feita no Paradox ou MySQL, criar // campos de saldo e custo unitário como tFloat Begin MyFieldCustoUnFloat := TFloatField.Create(Invent); With MyFieldCustoUnFloat do Begin FieldName := 'custoun'; Calculated := False; DataSet := Invent; Name := 'Invent'+'custoun'; Precision := 0; Size := 0; // sFormatoCusto depende de cada empresa; // Numa fabrica de raçoes, onde o custo unitário tem até quatro casas decimais, // é "0.0000"; num comércio comu, é "0.00" DisplayFormat := sFormatoCusto; EditFormat := sFormatoCusto; Invent.FieldDefs.Add(Name, ftFloat, 0, false); End; // Se tabela pelo MySQL, usar TFloat ********** Início ******** MyFieldSaldoFloat := TFloatField.Create(Invent); With MyFieldSaldoFloat do Begin FieldName := 'saldo'; Calculated := False; DataSet := Invent; Name := 'Invent'+'saldo'; Precision := 0; Size := 0; // sFormatoEstoque depende de cada empresa; // Numa loja que não tem estoque fracionado, será "0" e numa loja que tem // estoque fracionado (agropecuária por exemplo), pode ser "0.000" DisplayFormat := sFormatoEstoque; EditFormat := sFormatoEstoque; Invent.FieldDefs.Add(Name, ftFloat, 0, false); End;{With MyFieldEstestaFloat} // Se tabela pelo MySQL ou Paradox, usar TFloat ********** Fim ******** End Else Begin // Se tabela ttDbase ou ttFoxPro, usar TBCD ********** Início ******** MyFieldCustoUnBCD := TBCDField.Create(Invent); With MyFieldCustoUnBCD do Begin FieldName := 'custoun'; Calculated := False; DataSet := Invent; Name := 'Invent'+'custoun'; Precision := 0; Size := 4; // sFormatoCusto depende de cada empresa; // Numa fabrica de raçoes, onde o custo unitário tem até quatro casas decimais, // é "0.0000"; num comércio comu, é "0.00" DisplayFormat := sFormatoCusto; EditFormat := sFormatoCusto; Invent.FieldDefs.Add(Name, ftBCD, 4, false); End; MyFieldSaldoBCD := TBCDField.Create(Invent); With MyFieldSaldoBCD do Begin FieldName := 'saldo'; Calculated := False; DataSet := Invent; Name := 'Invent'+'saldo'; Precision := 0; Size := 3; // sFormatoEstoque depende de cada empresa; // Numa loja que não tem estoque fracionado, será "0" e numa loja que tem // estoque fracionado (agropecuária por exemplo), pode ser "0.000" DisplayFormat := sFormatoEstoque; EditFormat := sFormatoEstoque; Invent.FieldDefs.Add(Name, ftBCD, 3, false); End;{With MyFieldEstestaBCD} // Se tabela ttDbase, usar TBCD ********** Fim ******** End; {EndIf} // ********************** Definições dos campos. Final. End; {EndIf bFirstOpen then bFirstOpen := False; Invent.Open; Invent.First; StatusBar1.SimpleText := IntToStr(Invent.RecNo)+'/'+IntToStr(Invent.RecordCount); End Else Begin Invent.Close; StatusBar1.SimpleText := '0/0'; AbrirButton.Caption := '&Abrir'; End; {EndIf} .. .. ..Espero que seja de alguma utilidade!
Abraços!
Editado por paulobergoLink para o comentário
Compartilhar em outros sites
2 respostass a esta questão
Posts Recomendados
Participe da discussão
Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.