26
http://www.arquivodecodigos.net/dicas/delphi-efetuando-calculos-de-porcentagem-em- delphi-2707.html Efetuando cálculos de porcentagem em Delphi Cálculos de porcentagens estão presentes em boa parte das aplicações que desenvolvemos. Porém, há momentos em que a mente trava e não conseguimos lembrar com clareza como estes cálculos são feitos, principalmente em Delphi. Esta anotação tem o objetivo de ser uma fonte de pesquisa para os momentos em que suas habilidades matemáticas insistirem em continuar ocultas. Ex: 1 - Suponhamos que um produto que custe R$ 178,00 sofra um acréscimo de 15%. Qual o valor final do produto? Veja o código em Delphi: procedure TForm1.Button1Click(Sender: TObject); var valor, percentual, valor_final: double; begin valor := 178.00; // valor original percentual := 15.0 / 100.0; // 15% valor_final := valor + (percentual * valor); ShowMessage('O valor final do produto é: ' + FloatToStr(valor_final)); // O resultado será 204,70 end; Ex: 2 - Um produto, cujo valor original era de R$ 250,00, teve um desconto de 8%. Qual foi seu valor final? Veja o código em Delphi: procedure TForm1.Button1Click(Sender: TObject); var valor, percentual, valor_final: double; begin valor := 250.00; // valor original percentual := 8.0 / 100.0; // 8% valor_final := valor - (percentual * valor); ShowMessage('O valor final do produto é: ' + FloatToStr(valor_final)); // O resultado será 230,00 end; Ex: 3 - Em um concurso de perguntas e respostas, um jovem acertou 72 das 90 perguntas apresentadas. Qual foi a porcentagem de acertos? E a porcentagem de erros? Veja o código em Delphi: procedure TForm1.Button1Click(Sender: TObject); var perguntas, acertos: double; begin perguntas := 90.0; acertos := 72.0; ShowMessage('Porcentagem de acertos: ' + FloatToStr(((acertos / perguntas) * 100)) + '%'); ShowMessage('Porcentagem de erros: ' + FloatToStr((((perguntas - acertos) / perguntas) * 100)) + '%'); // Os resultados serão 80% e 20% end; Ex: 4 - Um aparelho de CD foi adquirido por R$ 300,00 e revendido por R$ 240,00. Qual foi a porcentagem de lucro na transação? Veja o código em Delphi:

Dicas Delphi

Embed Size (px)

Citation preview

Page 1: Dicas Delphi

http://www.arquivodecodigos.net/dicas/delphi-efetuando-calculos-de-porcentagem-em-

delphi-2707.html

Efetuando cálculos de porcentagem em Delphi Cálculos de porcentagens estão presentes em boa parte das aplicações que desenvolvemos. Porém, há momentos em que a mente trava e

não conseguimos lembrar com clareza como estes cálculos são feitos, principalmente em Delphi. Esta anotação tem o objetivo de ser uma fonte de pesquisa para os momentos em que suas habilidades matemáticas insistirem em

continuar ocultas.

Ex: 1 - Suponhamos que um produto que custe R$ 178,00 sofra um acréscimo de 15%. Qual o valor final do produto? Veja o código em Delphi:

procedure TForm1.Button1Click(Sender: TObject);

var

valor, percentual, valor_final: double;

begin

valor := 178.00; // valor original

percentual := 15.0 / 100.0; // 15%

valor_final := valor + (percentual * valor);

ShowMessage('O valor final do produto é: ' +

FloatToStr(valor_final));

// O resultado será 204,70

end; Ex: 2 - Um produto, cujo valor original era de R$ 250,00, teve um desconto de 8%. Qual foi seu valor final? Veja o código em Delphi:

procedure TForm1.Button1Click(Sender: TObject);

var

valor, percentual, valor_final: double;

begin

valor := 250.00; // valor original

percentual := 8.0 / 100.0; // 8%

valor_final := valor - (percentual * valor);

ShowMessage('O valor final do produto é: ' +

FloatToStr(valor_final));

// O resultado será 230,00

end;

Ex: 3 - Em um concurso de perguntas e respostas, um jovem acertou 72 das 90 perguntas apresentadas. Qual foi a porcentagem de acertos? E a porcentagem de erros? Veja o código em Delphi:

procedure TForm1.Button1Click(Sender: TObject);

var

perguntas, acertos: double;

begin

perguntas := 90.0;

acertos := 72.0;

ShowMessage('Porcentagem de acertos: ' +

FloatToStr(((acertos / perguntas) * 100)) + '%');

ShowMessage('Porcentagem de erros: ' +

FloatToStr((((perguntas - acertos) / perguntas) * 100)) + '%');

// Os resultados serão 80% e 20%

end; Ex: 4 - Um aparelho de CD foi adquirido por R$ 300,00 e revendido por R$ 240,00. Qual foi a porcentagem de lucro na transação? Veja o código em Delphi:

Page 2: Dicas Delphi

procedure TForm1.Button1Click(Sender: TObject);

var

v_ant, v_nov, p_lucro: double;

begin

v_ant := 300.0; // valor anterior

v_nov := 340.0; // valor novo

p_lucro := 0.0; // porcentagem de lucro

while(v_ant + ((p_lucro / 100.0) * v_ant) < v_nov) do

begin

p_lucro := p_lucro + 0.1;

end;

ShowMessage('A porcentagem de lucro foi de: ' +

FloatToStr(p_lucro) + '%');

// O resultado será 13,39

end; Ex: 5 - Uma loja repassa 5% do lucro a seus vendedores. Se um produto custa R$ 70,00, qual o valor em reais repassado a um

determinado vendedor? Veja o código em Delphi:

procedure TForm1.Button1Click(Sender: TObject);

var

valor, porcent, comissao: double;

begin

valor := 70.0; // valor do produto

porcent := 5.0 / 100.0; // 5%

comissao := porcent * valor;

ShowMessage('O valor repassado ao vendedor é: ' +

FloatToStr(comissao));

// O resultado será 3,5

end;

function Arredonda(Valor: Real): Real;

var

Modo: TFPURoundingMode;

begin

Modo := GetRoundMode;

try

SetRoundMode(rmTruncate);

Result := RoundTo(Valor, -2);

finally

SetRoundMode(Modo);

end;

end;

if FrmPrincipal.DSBotoes.State in [dsEdit,dsinsert] Then

DmDados.ProdutosPrecoVenda.AsFloat := Arredonda((DmDados.ProdutosPrecoCusto.AsFloat

-

Page 3: Dicas Delphi

((DmDados.ProdutosPrecoCusto.AsFloat *

DmDados.ProdutosDesconto

procedure TForm1.Button1Click(Sender: TObject);

var

valor, valor1, indice, resultado : Currency;

begin

valor := StrToCurr(StringReplace(Edit1.Text, '.', '', []));

valor1 := ( Valor /30 ) * StrToFloat(StringReplace(Edit2.Text, '.', '',

[]));

indice := StrToFloat(StringReplace(Edit3.Text, '.', '', []));

resultado := ( valor1 * indice) / 100; // so esta calculando para 30 dias

EXATO

Label2.Caption := FormatCurr('###,###,##0.00',resultado);

label3.Caption := FormatCurr('###,###,##0.00',valor-resultado);

end;

http://www.scriptbrasil.com.br/forum/lofiversion/index.php/t100022.html

Carlos Rocha

11/04/2007 - 13:09

Copiei essa procedure de um programa que baixei da net.

o programa, ele era Table da Guia BDE, eu coverti em Query do Zeos Lib.

Acontece que a linha "TmpQry.Connection := QryItens.Connection;", a conexao um está sendo

feita.

Codigo que copiei:

CODE

procedure tformcadpedidos.recalculapedido;

var

tmptable:ttable;

total:currency;

begin

Page 4: Dicas Delphi

tmptable:=ttable.Create(application);

try

tmptable.DatabaseName:=tableitens.DatabaseName;

tmptable.TableName:=tableitens.TableName;

tmptable.Open;

tmptable.FindKey([tablepedidosnumeropedido.asInteger]);

total:=0;

while (not tmptable.Eof) and

(tmptable.FieldByName('NumeroPedido').AsInteger=

tablepedidosnumeropedido.AsInteger) do

begin

total:=total+(tmptable.fieldbyname('valorunitario').AsCurrency *

tmptable.fieldbyname('quantidade').AsFloat);

tmptable.Next;

end;

finally

tmptable.Close;

tmptable.Free;

end;

statictexttotal.Caption:=formatcurr('###,###,##0.00',total);

end;

Codigo que transformei:(Não consigo criar a TmpQry de jeito nenhum)

CODE

procedure TCPedidos.RecalculaPedido;

var

TmpQry:TZQuery;

Total:Currency; // armazena valores do tipo moeda

begin

// cria um objeto Qry via codificação

TmpQry := TZQuery.Create(Application);

try

// define DatabaseName e QryName via codificação

TmpQry.Connection := QryItens.Connection;

TmpQry.Name := QryItens.Name;

TmpQry.SQL.Text := 'Select * from Itens';

TmpQry.Open;

//Observe que, para um novo pedido, o CodigoPedido ainda não foi gerado.Self

// Daí QryPedidosCodigoPedido.AsString sempre tera valor nulo e não terá ítens o pedido.

TmpQry.Locate('NumeroPedido', QryPedidosCodigoPedido.AsInteger, []);

Page 5: Dicas Delphi

// TmpQry.FindField(QryPedidosCodigoPedido.AsString);

Total := 0; // inicializa a variavel totalizadora

while (not TmpQry.Eof) and (TmpQry.FieldByName('NumeroPedido').AsInteger =

QryPedidosCodigoPedido.AsInteger) do

begin

// Acumula o Total da linha

Total := Total + (TmpQry.FieldByName('PrecoUni').AsCurrency *

TmpQry.FieldByName('Quantidade').AsFloat);

TmpQry.Next; // próximo registro

end;

finally

TmpQry.Close; // fecha a tabela

TmpQry.Free; // libera objeto da memória

end;

StaticTextTotal.Caption := FormatCurr('###,###,##0.00', Total);

end;

Micheus

11/04/2007 - 15:35

QUOTE(Carlos Rocha @ 11/04/2007 - 01:09)

...

Codigo que transformei:(Não consigo criar a TmpQry de jeito nenhum)

CODE

procedure TCPedidos.RecalculaPedido;

var

TmpQry:TZQuery;

Total:Currency; // armazena valores do tipo moeda

begin

// cria um objeto Qry via codificação

TmpQry := TZQuery.Create(Application);

try

// define DatabaseName e QryName via codificação

TmpQry.Connection := QryItens.Connection;

TmpQry.Name := QryItens.Name;

TmpQry.SQL.Text := 'Select * from Itens';

TmpQry.Open;

//Observe que, para um novo pedido, o CodigoPedido ainda não foi gerado.Self

// Daí QryPedidosCodigoPedido.AsString sempre tera valor nulo e não terá ítens o pedido.

TmpQry.Locate('NumeroPedido', QryPedidosCodigoPedido.AsInteger, []);

// TmpQry.FindField(QryPedidosCodigoPedido.AsString);

Page 6: Dicas Delphi

Total := 0; // inicializa a variavel totalizadora

while (not TmpQry.Eof) and (TmpQry.FieldByName('NumeroPedido').AsInteger =

QryPedidosCodigoPedido.AsInteger) do

begin

// Acumula o Total da linha

Total := Total + (TmpQry.FieldByName('PrecoUni').AsCurrency *

TmpQry.FieldByName('Quantidade').AsFloat);

TmpQry.Next; // próximo registro

end;

finally

TmpQry.Close; // fecha a tabela

TmpQry.Free; // libera objeto da memória

end;

StaticTextTotal.Caption := FormatCurr('###,###,##0.00', Total);

end;

Carlos Rocha, parece-me que você quer recalcular o valor total de um determinado pedido,

certo?!

Primeiramente algumas observações:

1) note que o exemplo original é limitado pelo uso de dataset do tipo Table. Quando você

utiliza dataset do tipo Query, muitas limitações não existem e facilidades nos estão

disponíveis;

2) a linha TmpQry.Name := QryItens.Name deverá resultar em problema já que os

identificadores devem ser únicos e deste modo você está tentando duplicar o nome do

componente;

3) quando você observa: Observe que, para um novo pedido, o CodigoPedido ainda não foi

gerado. Daí QryPedidosCodigoPedido.AsString sempre tera valor nulo e não terá ítens o

pedido.; entendo que não haveria nada a fazer (processar) neste caso;

4) apesar de estar comentada, a linha TmpQry.FindField(QryPedidosCodigoPedido.AsString);

não deve ser utilizada da forma como parece ter sido imaginada. FindField procura pelo nome

de um campo na lista de Fields do dataset, não nno resultado da consulta/tabela;

Então, vamos tentar abandonar alguns dos vícios impostos pelas limitações do Paradox e

simplificar.

Inicialmente, verificamos se devemos fazer, ou não, qualquer processamento em função da

situação do pedido (Novo ou não). Segundo sua observação, quando CodigoPedido for nulo

(novo pedido) ainda não haverão itens, logo, não faremos qualquer contabilização.

Já quando o pedido estiver gravado e poder ter itens, então vamos procurar pelos mesmos e

executar os cálculos. Entretanto, o SQL nos oferece funções como o SUM (somatório) que nos

permite enviar numa instrução SELECT a orientação para que o banco faça os cálculos e nos

retorne o resultado prontinho. Fazemos, então, uso deste recurso, limitando os itens a serem

calculados em função do CodigoPedido passado como parâmetro para a cláusula WHERE.

CODE

Page 7: Dicas Delphi

procedure TCPedidos.RecalculaPedido;

var

TmpQry:TZQuery;

Total:Currency; // armazena valores do tipo moeda

begin

StaticTextTotal.Caption := '0,00'; // se o pedido não tiver itens ou houver exception, este é o

valor apresentado

if not QryPedidosCodigoPedido.IsNull then

begin

// cria um objeto Qry via codificação

TmpQry := TZQuery.Create(Application);

try

// define DatabaseName e QryName via codificação

TmpQry.Connection := QryItens.Connection;

TmpQry.Name := 'TmpQry'; // *** o Nome do componente deve ser único!!!

TmpQry.SQL.Add('Select SUM(PrecoUni *Quantidade) as Total');

TmpQry.SQL.Add('From Itens');

TmpQry.SQL.Add('Where NumeroPedido = :NumeroPedido');

TmpQry.ParamByName('NumeroPedido').Value := QryPedidosCodigoPedido.AsInteger;

TmpQry.Open;

StaticTextTotal.Caption := FormatCurr('###,###,##0.00',

TmpQry.FieldByName('Total').Value);

finally

TmpQry.Free;

end;

end;

A forma como foi montada a instrução SQL (temos apenas a função de agregação - SUM no

SELECT) permite que omitamos a cláusula GROUP BY, utilizado quando queremos agrupar os

valores. Por exemplo, se fosse para gerar uma lista com o total de todos os pedidos, totalizado

pedido-a-pedido, teríamos de definí-la desta forma:

QUOTE

Select NumeroPedido, SUM(PrecoUni *Quantidade) as Total

From Itens

Group By NumeroPedido

Nesta situação, todos as colunas no SELECT, que não são função de agregação devem ser

colocadas na cláusula Group By.

Aquele AS antes do nome do campo que estamos calculando, não é obrigatório, mas no

MSAccess (se não me engano) é necessário.

Abraços

Carlos Rocha

Page 8: Dicas Delphi

12/04/2007 - 12:08

Ok, eu entendi.

Tentei usar da forma que você explicou, porem no caso de eu passar um novo

pedido(QryPedidos.insert), aí a variavel total não funciona, so fica 0,00.

Segue o código completo do Formulario.

CODE

unit CadPedidos;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ZDataset, DB, ZAbstractRODataset, ZAbstractDataset,

ZAbstractTable, Grids, DBGrids, StdCtrls, Buttons, DBCtrls, Mask,

ExtCtrls;

type

TCPedidos = class(TForm)

PanelDados: TPanel;

LabelCodigoPedido: TLabel;

LabelCodigoCliente: TLabel;

LabelLocalFatura: TLabel;

LabelLocalCobranca: TLabel;

LabelLocalEntrega: TLabel;

LabelCPF_CNPJ: TLabel;

LabelCEP: TLabel;

LabelDataCadastro: TLabel;

LabelTotalPedido: TLabel;

DBEditCodigoPedido: TDBEdit;

DBEditCodigoCliente: TDBEdit;

DBEditLocalFatura: TDBEdit;

DBEditLocalCobranca: TDBEdit;

DBEditLocalEntrega: TDBEdit;

DBEditCPF_CNPJ: TDBEdit;

DBEditCEP: TDBEdit;

DBEditDataCadastro: TDBEdit;

StaticTextTotal: TStaticText;

PanelBotoes: TPanel;

SpdBtnAlterar: TSpeedButton;

SpdBtnIncluir: TSpeedButton;

SpdBtnProcurar: TSpeedButton;

SpdBtnCancelar: TSpeedButton;

Page 9: Dicas Delphi

SpdBtnGravar: TSpeedButton;

SpdBtnExcluir: TSpeedButton;

DBNavigatorPedidos: TDBNavigator;

BitBtnFechar: TBitBtn;

DBGridItens: TDBGrid;

DSPedidos: TDataSource;

DSItens: TDataSource;

QryClientes2: TZQuery;

DSClientes: TDataSource;

QryPedidos: TZQuery;

QryItens: TZQuery;

QryClientes: TZQuery;

QryProdutos: TZQuery;

QryItensItem: TIntegerField;

QryItensNumeroPedido: TIntegerField;

QryItensCodigoProduto: TIntegerField;

QryItensQuantidade: TIntegerField;

QryItensPrecoUni: TIntegerField;

QryProdutosCodigoProduto: TIntegerField;

QryProdutosDescricao: TStringField;

QryProdutosPrecoUni: TIntegerField;

QryClientesCodigoCliente: TIntegerField;

QryClientesDataCadastro: TDateField;

QryClientesTipo: TStringField;

QryClientesCPF_CNPJ: TStringField;

QryClientesNome: TStringField;

QryClientesEndereco: TStringField;

QryClientesBairro: TStringField;

QryClientesCidade: TStringField;

QryClientesEstado: TStringField;

QryClientesTelefone: TStringField;

QryClientesEmail: TStringField;

QryItensTotal: TCurrencyField;

QryItensDescricao: TStringField;

QryClientes2CodigoCliente: TIntegerField;

QryClientes2DataCadastro: TDateField;

QryClientes2Tipo: TStringField;

QryClientes2CPF_CNPJ: TStringField;

QryClientes2Nome: TStringField;

QryClientes2Endereco: TStringField;

QryClientes2Bairro: TStringField;

QryClientes2Cidade: TStringField;

QryClientes2Estado: TStringField;

QryClientes2Telefone: TStringField;

QryClientes2Email: TStringField;

Page 10: Dicas Delphi

DBRadioGroupCondicaoPagamento: TDBRadioGroup;

SpeedButtonImprimir: TSpeedButton;

NomeCliente: TLabel;

DBLookupComboBoxNomeCliente: TDBLookupComboBox;

QryPedidosCodigoPedido: TIntegerField;

QryPedidosCondicaoPgto: TStringField;

QryPedidosDataCadastro: TDateField;

QryPedidosCodigoCliente: TIntegerField;

QryPedidosNomeCli: TStringField;

QryPedidosLocalFatura: TStringField;

QryPedidosLocalCobranca: TStringField;

QryPedidosLocalEntrega: TStringField;

QryPedidosCPF_CNPJ: TStringField;

QryPedidosCEP: TStringField;

QryPedidosNomeCliente: TStringField;

procedure FormClose(Sender: TObject; var Action: TCloseAction);

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure QryPedidosNewRecord(DataSet: TDataSet);

procedure QryItensNewRecord(DataSet: TDataSet);

procedure QryItensCalcFields(DataSet: TDataSet);

procedure QryItensBeforeInsert(DataSet: TDataSet);

procedure QryItensBeforePost(DataSet: TDataSet);

procedure DBGridItensKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

procedure QryItensCodigoProdutoValidate(Sender: TField);

procedure QryPedidosDataCadastroSetText(Sender: TField;

const Text: String);

procedure SpdBtnIncluirClick(Sender: TObject);

procedure SpdBtnAlterarClick(Sender: TObject);

procedure SpdBtnExcluirClick(Sender: TObject);

procedure SpdBtnGravarClick(Sender: TObject);

procedure SpdBtnCancelarClick(Sender: TObject);

procedure SpdBtnProcurarClick(Sender: TObject);

procedure DBLookupComboBoxNomeClienteClick(Sender: TObject);

procedure SpeedButtonImprimirClick(Sender: TObject);

procedure QryPedidosCPF_CNPJGetText(Sender: TField; var Text: String; DisplayText:

Boolean);

private

{ Private declarations }

procedure AtivarControles(Ativar: Boolean);

procedure RecalculaPedido;

public

{ Public declarations }

end;

Page 11: Dicas Delphi

var

CPedidos: TCPedidos;

implementation

uses dmsane, PesqPed, RelatorioPedidos, MaskUtils, Math;

{$R *.dfm}

procedure TCPedidos.FormCreate(Sender: TObject);

begin

QryProdutos.Open;

QryClientes.Open;

QryPedidos.Open;

QryItens.Open;

end;

procedure TCPedidos.FormClose(Sender: TObject; var Action: TCloseAction);

begin

Action:= cafree; // remove o form da memória

CPedidos := NIL; // informa que foi destruído (não criado)

end;

procedure TCPedidos.FormDestroy(Sender: TObject);

begin

QryProdutos.Close;

QryClientes.Close;

QryPedidos.Close;

QryItens.Close;

end;

procedure TCPedidos.QryPedidosNewRecord(DataSet: TDataSet);

begin

QryPedidosDataCadastro.AsDateTime := Date; //inicia com a data atual

end;

procedure TCPedidos.AtivarControles(Ativar: Boolean);

begin

PanelDados.Enabled := Ativar;

DBNavigatorPedidos.Enabled := (not Ativar);

DBGridItens.ReadOnly := (not Ativar);

SpdBtnIncluir.Enabled := (not Ativar);

SpdBtnAlterar.Enabled := (not Ativar);

Page 12: Dicas Delphi

SpdBtnExcluir.Enabled := (not Ativar);

SpdBtnGravar.Enabled := Ativar;

SpdBtnCancelar.Enabled := Ativar;

SpdBtnProcurar.Enabled := (not Ativar);

end;

{procedure TCPedidos.RecalculaPedido;

var

TmpQry:TZQuery;

Total:Currency; // armazena valores do tipo moeda

begin

// cria um objeto Qry via codificação

TmpQry := TZQuery.Create(Application);

try

// define DatabaseName e QryName via codificação

TmpQry.Connection := QryItens.Connection;

TmpQry.Name := QryItens.Name;

TmpQry.SQL.Text := 'Select * from Itens';

TmpQry.Open;

//Observe que, para um novo pedido, o CodigoPedido ainda não foi gerado.Self

// Daí QryPedidosCodigoPedido.AsString sempre tera valor nulo e não terá ítens o pedido.

TmpQry.Locate('NumeroPedido', QryPedidosCodigoPedido.AsInteger, []);

// TmpQry.FindField(QryPedidosCodigoPedido.AsString);

Total := 0; // inicializa a variavel totalizadora

while (not TmpQry.Eof) and (TmpQry.FieldByName('NumeroPedido').AsInteger =

QryPedidosCodigoPedido.AsInteger) do

begin

// Acumula o Total da linha

Total := Total + (TmpQry.FieldByName('PrecoUni').AsCurrency *

TmpQry.FieldByName('Quantidade').AsFloat);

TmpQry.Next; // próximo registro

end;

finally

TmpQry.Close; // fecha a tabela

TmpQry.Free; // libera objeto da memória

end;

StaticTextTotal.Caption := FormatCurr('###,###,##0.00', Total);

end;

}

procedure TCPedidos.RecalculaPedido;

var

TmpQry:TZQuery;

// Total:Currency; // armazena valores do tipo moeda

begin

Page 13: Dicas Delphi

StaticTextTotal.Caption := '0,00'; // se o pedido não tiver itens ou houver exception, este é o

valor apresentado

if not QryPedidosCodigoPedido.IsNull then

begin

// cria um objeto Qry via codificação

TmpQry := TZQuery.Create(Application);

try

// define DatabaseName e QryName via codificação

TmpQry.Connection := QryItens.Connection;

TmpQry.Name := 'TmpQry'; // *** o Nome do componente deve ser único!!!

TmpQry.SQL.Add('Select SUM(PrecoUni * Quantidade) as Total');

TmpQry.SQL.Add('From Itens Where NumeroPedido = :NumeroPedido');

TmpQry.ParamByName('NumeroPedido').Value := QryPedidosCodigoPedido.AsInteger;

TmpQry.Open;

StaticTextTotal.Caption := FormatCurr('###,###,##0.00',

TmpQry.FieldByName('Total').Value);

finally

TmpQry.Free;

end;

end;

end;

procedure TCPedidos.QryItensCalcFields(DataSet: TDataSet);

begin

if (QryItensQuantidade.AsFloat > 0) and (QryItensPrecoUni.AsCurrency > 0) then

QryItensTotal.AsCurrency := QryItensPrecoUni.AsCurrency *

QryItensQuantidade.AsFloat;

RecalculaPedido; // recalcula e exibe novamente

end;

procedure TCPedidos.QryItensNewRecord(DataSet: TDataSet);

begin

QryItensQuantidade.AsFloat := 1;

DBGridItens.SelectedIndex := 0; //código

end;

procedure TCPedidos.QryItensBeforeInsert(DataSet: TDataSet);

begin

if QryPedidosCodigoPedido.AsString = '' then

begin

if QryPedidos.State = dsInsert then

begin

// grava para salvar o número do pedido na tabela pai

QryPedidos.Post;

Page 14: Dicas Delphi

// ativa a alteração novamente

QryPedidos.Edit;

end;

end;

end;

procedure TCPedidos.QryItensBeforePost(DataSet: TDataSet);

begin

if QryItensNumeroPedido.AsString = '' then

QryItensNumeroPedido.AsInteger := QryPedidosCodigoPedido.AsInteger;

if QryItensCodigoProduto.AsString = '' then

begin

DBGridItens.SelectedIndex := 0; // seleciona a coluna código

ShowMessage('Código do produto deve ser informado!');

Abort; // interrompe a gravação

end;

if QryItensQuantidade.AsFloat <= 0 then

begin

DBGridItens.SelectedIndex := 2; // seleciona coluna quantidade

ShowMessage('Código do produto deve ser informado!');

Abort; // interrompe a gravação

end;

end;

procedure TCPedidos.DBGridItensKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

begin

// muda para a próxima coluna se pressionar Enter

if Key = VK_RETURN then // pressionou ENTER

begin

case DBGridItens.SelectedIndex of

0: DBGridItens.SelectedIndex := 2; //quantidade

1: DBGridItens.SelectedIndex := 2; //quantidade

2: DBGridItens.SelectedIndex := 3; //preço

else

DBGridItens.SelectedIndex := 0; //código

QryItens.Next;

if QryItens.Eof then

QryItens.Append;

end;

end;

end;

procedure TCPedidos.QryItensCodigoProdutoValidate(Sender: TField);

begin

Page 15: Dicas Delphi

if QryItensCodigoProduto.AsString <> '' then

begin

if QryProdutos.Locate('CodigoProduto', QryItensCodigoProduto.AsInteger, []) then

QryItensPrecoUni.AsCurrency := QryProdutosPrecoUni.AsCurrency

else

begin

ShowMessage('Código inválido');

Abort;

end;

end;

end;

procedure TCPedidos.QryPedidosDataCadastroSetText(Sender: TField;

const Text: String);

begin

if Text = ' / / ' then

Sender.Clear // apaga o campo data

else

// atribui a data digitada ao campo

try

Sender.AsString := Text;

except

ShowMessage('Data inválida!');

end;

end;

procedure TCPedidos.SpdBtnIncluirClick(Sender: TObject);

begin

AtivarControles(True); // ativa os controles para digitação

QryPedidos.Append; // inclui um novo registro na tabela

DBLookupComboBoxNomeCliente.SetFocus;

end;

procedure TCPedidos.SpdBtnAlterarClick(Sender: TObject);

begin

if QryPedidos.IsEmpty then

begin

// a tabela está vazia, então devemos incluir

SpdBtnIncluir.Click; // executa o click no botão

Exit; // retorna

end;

AtivarControles(True); // ativa os controles para digitação

QryPedidos.Edit; // permite alterar os dados

DBLookupComboBoxNomeCliente.SetFocus;

end;

Page 16: Dicas Delphi

procedure TCPedidos.SpdBtnExcluirClick(Sender: TObject);

begin

if Application.MessageBox('Deseja excluir este pedido?','Confirme',

MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2) = IDNO then

Exit; // retorna (sem fazer nada)

// devemos excluir os itens primeiro, para não termos registros órfãos

try

QryItens.First; // posiciona no primeiro item

while not QryItens.Eof do // executa até o fim do arquivo

begin

QryItens.Delete; // exclui o item

QryItens.First;

end;

QryPedidos.Delete; // exclui o pedido

except

ShowMessage('Ocorreu um erro durante a exclusão do pedido');

end;

end;

procedure TCPedidos.SpdBtnGravarClick(Sender: TObject);

begin

if QryPedidosCodigoPedido.AsInteger <= 0 then

begin

ShowMessage('Digite o número do pedido!');

// DBEditCodigoPedido.Enabled := true;

DBEditCodigoPedido.SetFocus;

end;

if DBRadioGroupCondicaoPagamento.Value = '' then

begin

ShowMessage('Escolha a Condição do Pagamento');

DBRadioGroupCondicaoPagamento.SetFocus; // posiciona o cursor

Abort; // não grava e continua editando

end;

if QryPedidosCodigoCliente.AsInteger > 0 then

begin

// procura pelo cliente usando o código

if not QryClientes.Locate('CodigoCliente', QryPedidosCodigoCliente.AsInteger, []) then

begin

ShowMessage('Código de cliente inválido!');

DBLookupComboBoxNomeCliente.SetFocus;

Exit;

end;

if QryPedidosCodigoCliente.AsString = '' then

Page 17: Dicas Delphi

begin

ShowMessage('Digite o Código do Cliente!');

DBEditCodigoCliente.SetFocus;

Exit;

end;

end;

if DBLookupComboBoxNomeCliente.Text = '' then

begin

ShowMessage('Por Favor! Escolha o Cliente!');

DBLookupComboBoxNomeCliente.SetFocus;

Exit;

end;

if DBEditLocalFatura.Text = '' then

begin

ShowMessage('Por Favor! Qual o local da Fatura!');

DBEditLocalFatura.SetFocus;

Exit;

end;

if DBEditLocalCobranca.Text = '' then

begin

ShowMessage('Por Favor! Qual o local de Cobrança!');

DBEditLocalCobranca.SetFocus;

Exit;

end;

if DBEditLocalEntrega.Text = '' then

begin

ShowMessage('Por Favor! Qual o local de Entrega!');

DBEditLocalEntrega.SetFocus;

Exit;

end;

if DBEditCPF_CNPJ.Text = '' then

begin

ShowMessage('Por Favor! Preencha o Documento!');

DBEditCPF_CNPJ.SetFocus;

Exit;

end;

if DBEditCEP.Text = '' then

begin

ShowMessage('Por Favor! Preencha o CEP!');

DBEditCEP.SetFocus;

Exit;

end;

QryPedidos.Post;

if QryItens.State in [dsInsert,dsEdit] then

Page 18: Dicas Delphi

QryItens.Post;

AtivarControles(False); // desativa os controles

end;

procedure TCPedidos.SpdBtnCancelarClick(Sender: TObject);

begin

QryPedidos.Cancel; // cancela inclusão/alteração

AtivarControles(False); // desativa os controles

end;

procedure TCPedidos.SpdBtnProcurarClick(Sender: TObject);

begin

Application.CreateForm(TPPedido, PPedido);

PPedido.Show;

end;

procedure TCPedidos.DBLookupComboBoxNomeClienteClick(Sender: TObject);

begin

QryClientes2.Close;

QryClientes2.sql.Clear;

QryClientes2.SQL.Add('Select * from Clientes where Nome =

'+''''+DBLookupComboBoxNomeCliente.Text+''''+'');

QryClientes2.Open;

QryClientes2.first;

while not QryClientes2.EOF do

begin

if QryClientes2Tipo.Value = 'F' then

begin

QryPedidosCPF_CNPJ.EditMask:='999\.999\.999\-99;0;_';

end

else

begin

QryPedidosCPF_CNPJ.EditMask:='99\.999\.999\/9999\-99;0;_';

end;

DBEditCPF_CNPJ.Text := QryClientes2.Fields[3].Value;

DBEditCodigoCliente.Text := QryClientes2.Fields[0].Value;

DBEditLocalCobranca.Text := QryClientes2.Fields[5].Value +', '+ QryClientes2.Fields[6].Value

+' - ' + QryClientes2.Fields[7].Value +'/' +QryClientes2.Fields[8].Value;

QryClientes2.Next;

end;

end;

procedure TCPedidos.SpeedButtonImprimirClick(Sender: TObject);

begin

Page 19: Dicas Delphi

QryPedidos.Filter := 'CodigoPedido = ' + DBEditCodigoPedido.Text;

QryPedidos.Filtered := true;

QryItens.Filter := 'CodigoPedido = ' + QryPedidosCodigoPedido.AsString;

QryItens.Filtered := true;

Application.CreateForm(TRPedidos, RPedidos);

RPedidos.QuickRepPedidos.PreviewModal;

RPedidos.Free;

end;

procedure TCPedidos.QryPedidosCPF_CNPJGetText(Sender: TField; var Text: String;

DisplayText: Boolean);

begin

if Sender.IsNull then

Text := ''

else

if length(Sender.AsString)=11 then

Text := FormatMaskText('999\.999\.999\-99;0;_', Sender.AsString)

else if length(Sender.AsString)=14 then

Text := FormatMaskText('99\.999\.999\/9999\-99;0;_', Sender.AsString);

end;

end.

Te enviei por email os arquivos do projeto pra você me dar uma ajuda.

Desde já meu muito obrigado.

Micheus

12/04/2007 - 14:12

QUOTE(Carlos Rocha @ 12/04/2007 - 12:08)

Ok, eu entendi.

Tentei usar da forma que você explicou, porem no caso de eu passar um novo

pedido(QryPedidos.insert), aí a variavel total não funciona, so fica 0,00.

Carlos Rocha, acho que não captei a idéia então. Quando você inclui um novo pedido,

inicialmente (até que ele tenha itens) ele não deveria apresentar o valor "0,00" ?

No comentário que eu fiz no post anterior, tomei como regra que em não havendo itens (caso

da inclusão) o valor do pedido apresentado seria "0,00":

3) quando você observa: Observe que, para um novo pedido, o CodigoPedido ainda não foi

gerado. Daí QryPedidosCodigoPedido.AsString sempre tera valor nulo e não terá ítens o

pedido.; entendo que não haveria nada a fazer (processar) neste caso;

Page 20: Dicas Delphi

Esta situação já estava descrita nesta linha do código sugerido:

StaticTextTotal.Caption := '0,00'; // se o pedido não tiver itens ou houver exception, este é o

valor apresentado

Abraços

Carlos Rocha

12/04/2007 - 17:45

você recebeu o e-mail que te passei no MSN?

La tem um arquivo zipado com todo o código do programa.

Micheus, da um olhada la que você vera qual é o problema.

Micheus

13/04/2007 - 12:20

QUOTE(Carlos Rocha @ 12/04/2007 - 05:45)

você recebeu o e-mail que te passei no MSN?

La tem um arquivo zipado com todo o código do programa.

Micheus, da um olhada la que você vera qual é o problema.

Recebi sim, mas como você trabalha com MySQL e como eu imaginava - não tenho a estrutura

do seu banco para gerá-lo aqui - logo, só posso ver suas telas mas não posso executar o

programa.

Se não tiver como gerar print-screen que mostrem a situação, então exporte a estrutura do

banco (metadata) para que eu possa tentar visualizar o que você está querendo que eu

entenda. Outra informação é a versão do Zeos que você utiliza, já que ao abrir o projeto, há

duas propriedades do componente TZQuery que minha versão (6.6.0 - beta) instalada não

reconhece.

Abraços

Carlos Rocha

13/04/2007 - 17:48

Observe que tem um arquivo com noime SaneRio.Sql, ele tem o script das minhas tabelas e só

abrir com o bloco de notas.

qualquer coisa, aí vai a estrutura:

Page 21: Dicas Delphi

CODE

CREATE TABLE IF NOT EXISTS clientes (

CodigoCliente int(4) unsigned NOT NULL auto_increment,

DataCadastro date NOT NULL DEFAULT '0000-00-00' ,

Tipo char(1) NOT NULL DEFAULT '' ,

CPF_CNPJ varchar(22) NOT NULL DEFAULT '' ,

Nome varchar(100) NOT NULL DEFAULT '' ,

Endereco varchar(200) NOT NULL DEFAULT '' ,

Bairro varchar(200) NOT NULL DEFAULT '' ,

Cidade varchar(200) NOT NULL DEFAULT '' ,

Estado varchar(200) NOT NULL DEFAULT '' ,

Telefone varchar(22) NOT NULL DEFAULT '0' ,

Email varchar(100) ,

PRIMARY KEY (CodigoCliente)

);

CREATE TABLE IF NOT EXISTS fornecedores (

CodigoFornecedor int(4) unsigned NOT NULL auto_increment,

DataCadastro date NOT NULL DEFAULT '0000-00-00' ,

Tipo char(1) NOT NULL DEFAULT '' ,

CPF_CNPJ varchar(22) NOT NULL DEFAULT '' ,

Nome varchar(100) NOT NULL DEFAULT '' ,

Endereco varchar(200) NOT NULL DEFAULT '' ,

Bairro varchar(200) NOT NULL DEFAULT '' ,

Cidade varchar(200) NOT NULL DEFAULT '' ,

Estado varchar(200) NOT NULL DEFAULT '' ,

Telefone varchar(22) NOT NULL DEFAULT '0' ,

Email varchar(100) ,

PRIMARY KEY (CodigoFornecedor)

);

CREATE TABLE IF NOT EXISTS itens (

Item int(4) unsigned NOT NULL auto_increment,

NumeroPedido int(4) NOT NULL DEFAULT '0' ,

CodigoProduto int(4) NOT NULL DEFAULT '0' ,

Quantidade int(4) NOT NULL DEFAULT '0' ,

PrecoUni int(11) NOT NULL DEFAULT '0' ,

PRIMARY KEY (Item)

);

Page 22: Dicas Delphi

CREATE TABLE IF NOT EXISTS pedidos (

CodigoPedido int(4) unsigned NOT NULL auto_increment,

CondicaoPgto varchar(200) NOT NULL DEFAULT '' ,

DataCadastro date NOT NULL DEFAULT '0000-00-00' ,

CodigoCliente int(4) NOT NULL DEFAULT '0' ,

NomeCli varchar(100) NOT NULL DEFAULT '' ,

LocalFatura varchar(200) NOT NULL DEFAULT '' ,

LocalCobranca varchar(200) NOT NULL DEFAULT '' ,

LocalEntrega varchar(200) NOT NULL DEFAULT '' ,

CPF_CNPJ varchar(22) NOT NULL DEFAULT '' ,

CEP varchar(20) NOT NULL DEFAULT '' ,

PRIMARY KEY (CodigoPedido)

);

CREATE TABLE IF NOT EXISTS produtos (

CodigoProduto int(4) unsigned NOT NULL auto_increment,

Descricao varchar(200) NOT NULL DEFAULT '' ,

PrecoUni int(11) NOT NULL DEFAULT '0' ,

PRIMARY KEY (CodigoProduto)

);

Micheus

13/04/2007 - 19:55

QUOTE(Carlos Rocha @ 13/04/2007 - 05:48)

Observe que tem um arquivo com noime SaneRio.Sql, ele tem o script das minhas tabelas e só

abrir com o bloco de notas.

Não sei o que é que eu estava procurando, porque não enxerguei este arquivo - agora eu o

encontrei.

Vou verificar e até amanhã dou um "parecer" - ainda tenho que instalar o MySQL aqui em

casa.

Carlos Rocha

13/04/2007 - 20:04

então ok.

Ficarei aguardando.

Desde já meu muito obrigado pela atenção

Micheus

14/04/2007 - 15:31

Page 23: Dicas Delphi

Carlos Rocha, cara tive um trabalhinho extra, já que você não me respondeu que versão do

Zeos está utilizando - As versões recentes não apresentam as propriedades RequestLive e

ShowRecordTypes no componente TZQuery e que o compilador insistia em utilizar - tive que

remover seus componentes e adicionar os da minha paleta (claro que só troquei os da tela de

pedidos).

Primeiramente, acho que seria interessante você definir os relacionamentos em seu banco de

dados caso não os tenha definido (no script não havia nenhuma definição) - isso garantirá a

integridade das informações e dará um aspecto mais profissional ao seu projeto. Em Paradox

este recurso era problemático, porque neste "protótipo de banco" os arquivos corrompem

com certa facilidade - o que não é fácil com banco de dados "de verdade". Se precisar de uma

ferramenta de modelagem de dados para o MySQL dê uma olhada neste post.

Executando o programa, consegui realmente ver o que você queria dizer, entretanto o

problema ocorre devido ao fato de ter sido definido o relacionamento entre os dataset's

QryPedidos e QryItens dentro do programa. Isso poderia ser feito utilizando Filter, clausula

WHERE e deveria funcionar também ao setar MasterSource/MasterField/LinkedFields. Eu

prefiro utilizar a cláusula WHERE.

Então a sugestão para correção seria substituir o SQL de QryItens para:

CODE

Select * from Itens

where NumeroPedido = :CodigoPedido

E associar a sua propriedade DataSource o datasource DSPedidos de onde será obtido o

parâmetro CodigoPedido definido no novo SQL. Deste modo, ao abrir QryItens, será filtrado

apenas os itens correspondentes ao Pedido selecionado.

Na procedure RecalculaPedido substitua:

StaticTextTotal.Caption := FormatCurr('###,###,##0.00', TmpQry.FieldByName('Total').Value);

por

StaticTextTotal.Caption := FormatCurr('###,###,##0.00',

TmpQry.FieldByName('Total').AsCurrency);

isso evitará erro quando Total for nulo (ocorre sempre que não existirem itens ainda). Quando

você utiliza o AsCurrency a conversão é feita implicitamente e você tem como resultado 0

(zero).

O evento OnCalcFields ocorre para cada item existente no DBGrid, assim recalcular o total a

cada evento não será muito interessante. Digamos que o lógico seria:

- quando mudamos de pedido;

- quando gravamos um item do pedido (post de um insert ou edit);

- quando excluímos um item do pedido.

Page 24: Dicas Delphi

Assim a sugestão seria utilizar o evento AfterPost, AfterDelete de QryItens e o evento

OnDataChange do datasource DSPedidos:

CODE

procedure TCPedidos.QryItensAfterPost(DataSet: TDataSet);

begin

RecalculaPedido;

end;

esta procedure seria atribuída ao evento AfterDelete também (é só associar o evento ao

procedimento já existente)

CODE

procedure TCPedidos.DSPedidosDataChange(Sender: TObject; Field: TField);

begin

RecalculaPedido;

end;

Faça a ordenação dos seus campos na tela - o Tab Order, já que é chato você teclar TAB e ir

para outro campo que não seja o próximo.

Dê uma olhada no evento OnClick do botão de impressão do relatório, você vai observar que

no texto da propriedade Filter do dataset QryItens você está utilizando "CodigoPedido = ...",

mas o nome do campo na tabela de itens na verdade é NumeroPedido! (aqui você é vítima de

sua própria pegadinha...). É conveniente que os campos de relacionamentos tenham o mesmo

nome nas tabelas envolvidas.

Voce enctrará outros pequenos problemas, mas é melhor que você os encontre.

Por hora acho que é só, espero não ter esquecido de nada.

Abraços

Carlos Rocha

14/04/2007 - 17:14

Desculpe.

É ZeosDbo 6.6.0

Carlos Rocha

Page 25: Dicas Delphi

21/04/2007 - 15:14

Ok

Eu queria agora o Seguinte:

Fiz o meu QReport(Relatório), só que eu preciso que as bordas de cada QRBand, tenham

cantos arredondados e preciso tambem, colocar uma figura da Logo da empresa no topo do

Relatório e mais uma coisa, Na Aba "Detail", eu queria que, mesmo tendo apenas 2 ou 3 ítens

o pedido(por exemplo), a borda fizesse linhas entre eles pelo menos ate que uma folha de

"A4" se acabasse.

Um abraço.

Micheus

21/04/2007 - 15:39

QUOTE(Carlos Rocha @ 21/04/2007 - 03:14)

Eu queria agora o Seguinte:

Fiz o meu QReport(Relatório), só que eu preciso que as bordas de cada QRBand, tenham

cantos arredondados e preciso tambem, colocar uma figura da Logo da empresa no topo do

Relatório e mais uma coisa, Na Aba "Detail", eu queria que, mesmo tendo apenas 2 ou 3 ítens

o pedido(por exemplo), a borda fizesse linhas entre eles pelo menos ate que uma folha de

"A4" se acabasse.

Melhor seria você literalmente desenhar.

Dá para fazer uma prévia do que você quer e postar um link da imagem? Acho que ficaria mais

fácil alguém dar sugestões.

Mas para adiantar, a parte do logo é só você adicionar uma banda Title e colocar um

componente TQRImage (se vier do disco) ou TQRDBImage (se vier do banco).

No caso do borda do Detail, não resolve você definir a propriedade Frame.DrawBottom = True

?

Abraços

Carlos Rocha

21/04/2007 - 16:32

Não funciona porque o que eu quero é que, alem de ter a Borda, que a borda seja com os

cantos arredodados.

Da uma revisada na perguta fazendo favor.

Page 26: Dicas Delphi

Valeu.

Micheus

22/04/2007 - 15:26

QUOTE(Carlos Rocha @ 21/04/2007 - 04:32)

Não funciona porque o que eu quero é que, alem de ter a Borda, que a borda seja com os

cantos arredodados.

Da uma revisada na perguta fazendo favor.

Carlos Rocha, não conheço outro meio que não seja escrevendo um componente para isso.