Upload
dochagas
View
257
Download
6
Embed Size (px)
Citation preview
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:
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
-
((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
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, []);
// 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);
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
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
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;
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;
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;
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);
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
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;
// 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
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;
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
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
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
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;
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:
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)
);
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
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.
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
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.
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.