Ir para conteúdo
Fórum Script Brasil

Micheus

Veteranos
  • Total de itens

    3.189
  • Registro em

  • Última visita

Tudo que Micheus postou

  1. Mesfistofeles, observei que este efeito ocorre no próprio MSAccess (o gerenciador do banco) quando ao invés de usar como separador de decimais a vírgula, usei o ponto. Só para constar, no MSAcces o equivalente ao tipo currency (valor monetário) seria o tipo Moeda. No Delphi, usando um TADOTable oo campo Moeda é "traduzido" em um TBCDField: Declaração no Access => No Delphi (Field) Moeda => TBCDField Numérico - Duplo => TFloatField Numérico - Simples => TBCDField Numérico - Decimal => TFloatField Eu criei uma pequena aplicação para testar este comportamento que você postou e não observei o problema. Utilizei um TADOConnection com provider: Microsoft.Jet.OLEDB.4.0; No banco, os campos VlrUnitario e VlrTotal do tipo Moeda e o campo QtdTotal do tipo Numero - Duplo; Coloquei um DBGrid para monitorar os dados no TADOTable; Dois TDBEdit para editar os campos VlrUnitario e QtdTotal e um TDBText para observar o valor VlrTotal; Não foi utilizada qualquer formatação; No evento OnChange dos campos multiplicados o resultado era atribuido ao total. (se quiser vê-la, envie-me seu e-mail por MP) Abraços
  2. nsouza, algum adendum ao que o colega Zuera postou... Supondo que você use a query (Query1) para fazer a consulta no banco pelo nº da OS desejada, faça isto de forma a poupar tráfego de dados entre sua aplicação e o servidor. Digamos que você quer apenas conferir se o número existe e não vai precisar trazer mais nenhuma informação desta OS caso ela exista, então, não use o "*", use apenas o próprio campo: select NumOS from OrdemServico where NumOs = :NumOS Antes de executar a query, você deve passar o parâmetro NumOS (aquele que está declarado logo após o ":") ... Query1.ParamByName('NumOS').AsString := Edit1.Text; Query1.Open; Considerando que você passou o nome tblOrdemServico, parece que você está utilizando um componente tipo table e talvez você apenas queira posicionar esta table no NumOS que o cara digitar. Para este caso, se esta sua tabela contiver um índice para o campo NumOS e você o tiver selecionado na propriedade IndexFieldName, você pode fazer uso do método FindKey ou até mesmo Locate. Zuera, é uma das práticas o uso de validação quando o usuário digita o ENTER (coisa herdada do bom e velho DOS), mas na prática, não há garantias de que o usuário vai fazer isto. No Windows (ambiente gráfico), é muito comum que o usuário use o mouse para mudar de campo e, neste caso, a opção citada pelo colega nsouza torna-se mais acertada (usar o evento OnExit) - assim a validação fica em um lugar só (ou é feita apenas uma única vez). O código que você postou, continua valendo para o uso neste evento - sem problemas. Mas, supondo que o colega use ele, com a query e tudo, há uma correção a fazer que é apontar a ele onde a parametrização e abertura da query devem ser feitas: 1) Mantendo o código no evento OnKeyPress. Vamos observar que para todas as opções dadas, a tecla pressionada teria que ser #13, então: procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin if key = #13 then begin if Edit1.Text = '' then begin Application.MessageBox('Digite algo para a pesquisa.','Título', MB_ok + MB_defbutton1 + MB_iconexclamation); end else begin Query1.ParamByName('NumOS').AsString := Edit1.Text; Query1.Open; if Query1.IsEmpty then begin Application.MessageBox('Este número não foi cadastrado','Título',MB_ok + MB_defbutton1 + MB_iconexclamation); end else if not Query1.IsEmpty then begin Application.MessageBox('O registro já existe','Título',MB_ok + MB_defbutton1 + MB_iconexclamation); Edit1.SetFocus; Abort; end; end; end; a chamada a Abort não seria necessária, já que não há mais nenhum código neste procedimento que pudesse ser executado após a mensagem. 2) Colocando o código no evento OnExit: procedure TForm1.Edit1Exit(Sender: TObject); begin if Edit1.Text = '' then ShowMessage('Digite algo para a pesquisa'); else begin Query1.ParamByName('NumOS').AsString := Edit1.Text; Query1.Open; if Query1.EOF then ShowMessage('Este número não foi cadastrado'); else begin Edit1.SetFocus; ShowMessage('O registro já existe'); end; end; end; Uma dica: pensando de forma mais profissional, você não deve fazer um teste deste tipo: if Query1.IsEmpty = true then Lembrem-se de que a expressão a ser avaliada pelo if será sempre uma expressão booleana (algo que retorne True ou False), logo, não faz sentido você testar if true = true then, basta que você use if true then. A expressão que não for verdadeira resultará na execução do código no else.
  3. Mesfistofeles, perguntinhas básicas... - qual banco de dados você está usando? - qual o tipo de dados que você usou no banco para este campo? - voce adicionou os campos ao dataset. você mexeu na propriedade Currency do field? - voce colocou alguma formatação na propriedade DisplayFormat? - está usando o método OnGetText de algum destes fields? - a "diferença" de duas casas está sendo visualizada na tela do seu projeto ou quando você confere o valor no banco?
  4. x_Vovo_x, tem jeito sim.Coloque um componente TMainMenu (MainMenu1) no seu form e não adicione nenhum item a ele - este será o menu de sua aplicação (ela só pode ter um). Depois adicione outros dois TMainMenu (MainMenu2 e MainMenu3) e nestes você faz a configuração dos itens conforme necessário. Para usar um deles você usa o método Merge do MainMenu1 - isto fará com que os itens do menu utilizado "passem" para o MainMenu1 e apareçam na sua aplicação. Por exemplo, para mostrar o MainMenu3 e "esconder" o MainMenu2 você usaria estes comandos: .. MainMenu1.UnMerge(MainMenu2); MainMenu1.Merge(MainMenu3); Como você vê, caso sua aplicação utilize dois menus, mas que tenham algumas opções comum, talvez você possa simplesmente colocar estas opções comuns no menu principal (MainMenu1) e mesclar (Merge) ele com as opções dos outros menus conforme o caso. Abraços
  5. flavioavilela, considerando que a forma de pagamento e as outras informações parecem ser aquelas que fazem parte da venda (mestre), quando você precisa fazer um relatório com estas características, normalmente você usa a sequência:- uma banda group header, com Expression contendo o campo chave da venda => onde estão os dados do cabeçalho da venda - uma banda detail => onde vão os itens daquela venda - uma banda group footer => onde estão outras informações sobre a venda que você quer que apareçam após os itens. Há outras formas de fazer isto, mas acho que esta já vai lhe servir. Abraços
  6. :huh: :blink: Acho que você está falando sobre obter o código gerado para o registro que você acabou de inserir, não seria isto? Isto é algo que eu no momento não saberia lhe dizer exatamente, mas programando em Delphi, deveria ser possível você obtê-lo logo após ao post. Se não me engano, ao usar o componente TZUpdateSQL(da biblioteca ZeosLib), a propriedade UseSequenceFieldForRefreshSQL viabiliza a obtenção dos campos auto-numeração (sequence) após o post/commit. Abraços
  7. sergio.lima, foi falha minha. Respondi e nem conferi antes de enviar (estava saindo). Eu sugiro que você use alias para facilitar sua vida. Quando não se põe um nome, se você tiver outros sum, os campos ficarão tipo: sum, sum1, sum2; e não é muito legal. Faça como abaixo: dtmdlClube.SQLdtstAuxiliar.CommandText := 'select sum(VALOR) SUM_VALOR from CAIXA where DATA=:Data and TIPO=:Tipo'; ou dtmdlClube.SQLdtstAuxiliar.CommandText := 'select sum(VALOR) AS SUM_VALOR from CAIXA where DATA=:Data and TIPO=:Tipo'; O alias (apelido para o campo) você escolhe o que quiser, mas declara do modo como está em negrito - logo após a função. Então, você usa este nome para acesso ao resultado. Abraços
  8. sergio.lima, se você precisa do valor por uma determinada data e o tipo, então você não precisa da cláusula order by, pois vai solicitar ao banco uma coisa que não vai usar (só haverá uma data e um tipo). A questão da totalização em si deveria estar sendo feita pelo sum. Eu sugiro que você parametrize a query para não ter problemas com data (principalmente se você vier a usar seu sistema com outro banco no futuro). O firebird usa a data string no formato dd.mm.yyyy ou, se você usar a barra, mm/dd/yyyy. Usar uma string diferente deste formato vai resultar em resultado nulo. O MySQL, já usa yyyy-mm-dd; .... Usando a parametrização, você passa a informação como tdate/tdatetime e o driver faz a conversão conforme o caso. ... dtmdlClube.clntdtstAuxiliar.Close; dtmdlClube.SQLdtstAuxiliar.CommandText := 'select sum(VALOR) from CAIXA where DATA=:Data and TIPO=:Tipo'; dtmdlClube.clntdtstAuxiliar.Params.ParamByName('Data').AsDate := fData; dtmdlClube.clntdtstAuxiliar.Params.ParamByName('Tipo').AsString := 'E'; dtmdlClube.clntdtstAuxiliar.Open;
  9. Eder Moraes, em se tratando de desenho do texto, em modo gráfico, onde os caracteres tem larguras diferentes, este tipo de alinhamento não é apropriado. Ele funciona bem quando você está imprimindo em modo caracter (como, nas matriciais). A função abaixo é genérica (você pode pô-la em uma unit de utilidades), centraliza o texto verticalmente e permite que você defina qual o alinhamento horizontal desejado: // procedimento para cálculo e desenho das células procedure DrawAligned(Grid :TObject; aCol, aRow :Integer;Rect :TRect; Alignment :TAlignment); var XOffset, YOffset, RectWidth :SmallInt; Text :String; begin with TStringGrid(Grid) do begin Text := Cells[aCol, aRow]; // desenhando o retângulo (célula) Canvas.Pen.Color := clBtnShadow; // cor das linhas Canvas.Brush.Style := bsSolid; with Rect do Canvas.Rectangle(Left -1, Top -1, Right +1, Bottom +1); // preparação do alinhamento horizontal RectWidth := Rect.Right -Rect.Left; case Alignment of taLeftJustify: XOffset := Rect.Left +2; taCenter : XOffset := Rect.Left +(RectWidth -Canvas.TextWidth(Text)) div 2; taRightJustify: XOffset := Rect.Left +(RectWidth -Canvas.TextWidth(Text)) -3; end; // preparação do alinhamento vertical YOffset := Rect.Top +(((Rect.Bottom -Rect.Top) -Canvas.TextHeight('Lj')) div 2); // desenhando o texto na célula Canvas.Brush.Style := bsClear; Canvas.TextRect(Rect, XOffset, YOffset, Text); end; end; Para usá-la, no evento OnDrawCell do TStringGrid, você faz a chamada passando os parâmetros necessários. Digamos que temos 4 colunas e que elas possuem alinhamentos diferentes, então, programamos o evento para testar a couna e desenhá-la conforme desejado: procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin case ACol of 0 : DrawAligned(Sender, ACol, ARow, Rect, taCenter); // centralizado 1, 2 : DrawAligned(Sender, ACol, ARow, Rect, taLeftJustify); // alinhado a esquerda 3 : DrawAligned(Sender, ACol, ARow, Rect, taRightJustify); // alinhado a direita end; end; Se não esqueci de nada, é isto. Abraços
  10. prod, sendo auto-incrementado você não tem mesmo controle algum sobre este número - na aplicação muiti-usuário o banco irá gerenciar corretamente este campo, evitando qualquer possibilidade de duplicação ou falha na continuidade dele. Se fosse controlado via programação, como eu disse antes, você teria que obter este número (max +1) apenas momentos antes de gravar a informação efetivamente (normalmente seria em uma trigger). Lembre-se que para minimizar o risco de mais que um usuário obter o mesmo código, ele deve ser obtido num último momento. Não sei exatamente qual a necessidade de você ter esta informação antes de gravar o registo, mas não é uma boa prática pelo que já comentei. Se isto realmente é importante, então o único modo que vejo é você usar uma tabela para fazer o gerenciamento dos códigos, mas não sei até onde isso valeria a pena. Espero que mais algum outro colega se manifeste a respeito. Abraços
  11. paulobergo, eu tenho o BDE instalado em um XP (SP2) e os alias aparecem normalmente para qualquer usuário (quando visualizo no BDEAdmin). A informação dos alias fica no arquivo Idapi32.cfg e, em teoria, teria mesmo que ficar disponível a qualquer usuário. No registro do Windows, a informação está na chave LOCAL_MACHINE (que é comum a todos os usuários): chave: HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine valor: CONFIGFILE01 dados do valor: C:\Arquivos de programas\Arquivos comuns\Borland Shared\BDE\Idapi32.cfg Nas diretivas de segurança da pasta só não estão habilitadas: Controlte total e Permissões especiais Nas pastas onde estão os dados, os usuários também tem as mesmas permissões. Eventualmente, se conseguir ter acesso a pasta dos dados, talvez você pudesse avaliar a possibilidade de usar alias dinâmicos. Faz um tempinho eu falei sobre ele deste post em diante. Abraços
  12. Eliminando as dúvidas... ZueRa, eu lhe perguntaria qual o objectivo do código acima, mas como você já achou a solução, não vou entrar nesta questão. Lembre-se sempre de usar a tag CODE no lugar de QUOTE para mostrar seu código. Veja como fica melhor a visualização do código da forma como está aqui. Quanto ao erro, você deve saber que a função DrawText é uma função da API. Se você pesquisar no help (Windows SDK) verá que o último parâmetro esperado pode ser uma "concatenação" de flags, que são na verdade words com valores binários - cada flag tem um determinado bit ligado (que representa a opção) e por isso utiliza-se do OR (operação binária). Voce não postou a declaração do seu Align, então não dá para saber exatamente como sugerir a correção do erro. A mensagem sugere que você não declarou ele como sendo um array of, visto que você fez uso dele como se o fosse. Então o compilador diz: "requirido tipo array". Aqui o problema está associado ao uso dos objetos utilizados na cláusula with ... do. É uma boa opção para evitar longas linhas no código, mas perde-se um pouco da visibilidade de que propriedade/método pertence a quem. Observe a linha onde ocorreu o erro; veja que propriedade está sendo usada ali (State). Agora, avalie os objetos colocados na cláusula with; Existem três deles que tem uma propriedade exatamente com este nome, são eles:DBGrid1, DataSource e DataSet. Então, como pode o compilador ter certeza de qual usar? Ele provavelmente considerou que fosse o do DataSet (último lista, supondo que ele usou o último da pilha), do contrário, DBGrid1 sendo o primeiro, não teria ocorrido o erro. Então, quando há esta ambiguidade, você deve "esquecer" o with (nesta linha) e preceder a propriedade/método como o nome do objeto que você quer referenciar. Neste caso, na linha onde ocorreu o erro, ela deveria ficar: if gdSelected in DBGrid1.State then begin Isto também é válido para funções/variáveis que estejam declaras com o mesmo nome em units diferentes. Abraços
  13. Este var é a cláusula que identificar o lugar onde você estará declarando as variáveis que irá usar no programa. Rajare, não leve a mal a observação, mas é realmente importante que você leia aquele material que o colega Jhonas lhe indicou no seu outro tópico. Sabemos que você voltará a fazer novas questões aqui e vai ficar muito complicado tentar lhe ajudar sem que você tenha o conhecimento básico na linguagem. Muitas vezes no ímpeto de aprender algo novo e interessante queremos nos atirar direto nele, mas não é uma boa estratégia. Pela falta de conhecimento talvez você não entenda direito o que vou dizer, mas vamos tentar:É muito simples fazer esta validação, se você considerar que um campo TDate/TDateTime são números do tipo double. A parte inteira armazena os dias e a fracinária as horas. Veja este post mais detalhado. Assim, se você pegar a data digitada e subtrair 1, o resultado será o dia anterior e você poderá comparar com a data em questão. Se é igual (verdadeiro) então faz algo, senão, é diferente (falso) e faz outra coisa (diz que tá errado e tal...). Abraços
  14. Case dbrg_Turma.ItemIndex of 2: begin dbrg_Ano.ItemIndex := 2; db_Evento.SetFocus; end; end; Faça assim que ficará mais apropriado - não tem porque você testar uma variável/propriedade com um mesmo valor duas vezes. ;) Como qualquer outra estrutura lógica, você pode usar o demarcador de blocos (begin..end) e executar várias tarefas em cada condição. não saberia indicar não. Procure por apostilas sobre delphi básico que deverá aparecer algo a respeito. Mas, se não tiver problemas com inglês, use o help - é muito bom. Por hora fica este link com exemplos. resumidamente... if <condição verdadeira> then ... else ... se <condição verdadeira> então ... senão ... case <expressão seletora> of <valor1> <valor2> ... else end; caso <expressão seletora> "seja" <valor1> <valor2> ... senão end fique a vontade. Siga o que deveria ser o padrão e acrescente (Resolvido) na frente do título atual. ;) Abraços
  15. Igor Leonne, tenho a impressão de que você pode usar dois TStringGrid's. Para um deles você define a quantidade de linha(RowCount) e coluna(ColCount) como você citou e para o outro apenas uma linha.No caso de você não usar um cabeçalho (acho que seria o caso do segundo), você define a propriedade FixedRows = 0 (o mesmo vale para colunas - FixedCols). Se o primeiro grid não puder ser editado pelo usuário, você desabilita a todo o grid usando a propriedade Enabled = False. A linha e colunas atualmente selecionadas são obtidas pelas propriedades Row e Col, respectivamente. O item (célula) é lido através da propriedade Cells[<col>, <row>]. Dê uma olhada nele e veja se é por ai a solução do seu problema.
  16. Rajare, se você entendeu o que este "comando" faz, deve ter observado que ele ocorre quando há uma mudança no groupbox da primeira coluna. O que você quer fazer, dar foco aos edits, irá ocorrer quando houver uma mudança no groupbox da segunda coluna e quando o item selecionado for o correspondente a Outros - a idéia é bem similar a esta que você implementou, apenas que irá mexer com o foco de outro componente.Veja se consegue implementar. Abraços p.s.: não sofra com uso de formatações ao postar o código com "sintax highlight - apenas use a tag CODE ali da barrinha de botões. ;)
  17. Rajare, o TRadioGroup só permite a seleção de um item de cada vez - é a finalidade deste tipo de componente. Então, não tem como você fazer isto que você quer, uma vez que ambos itens estão no mesmo radio group. Mas... Sabendo disto, você pode implementar algum meio de contornar esta situação. Basta você entender que pode usar os componentes TRadioButton e que quando você coloca mais que um em um mesmo componente (TGroupBox, TPanel, TForm, ...), eles comportam-se como se fosse um TRadioGroup e operam juntos. Dependendo de como vai funcionar a lógica total destes seus botões, você poderia colocar no form um TGroupBox; dentro dele dois TPanel (um ao lado do outro), sendo o primeiro a coluna onde estará as Turmas e evento e na segunda coluna estarão os outros itens. Voce terá que verificar qual o radio button está selecionado através da propriedade Checked de cada um deles. Para monitorar quando um deles é pressionado, você usa o evento OnClick (você pode usar um evento para cada grupo - não precisa ser para cada radio button). Abraços
  18. Igor Leonne, você está falando sobre criar um componente tipo datagrid para Win32, ou sobre usar o DataGrid do .NET, ou sobre simplesmente como usar o TDBGrid (Win32)? Visualizando imagem no DataGrid (.NET - ref. ActiveDelphi) Delphi 2005, ASP.NET e DataGrid ()ref. DevMedia) Quando fala em "ferramenta datagrid", tenho a impressão de que não é nada disso que citei, mas... ... como uma ferramenta de extração de dados pode ser bastante complexa - talvez seja difícil achar um tutorial simples.
  19. Mesfistofeles, o primeiro SQL irá somar todos os itens referentes a venda nun_venda, enquanto que o segundo irá "listar" todos os itens referentes a venda nun_venda - são duas coisas diferentes. Assim, acho que apenas você é quem podo responder a esta pergunta (não sabemos o que você quer fazer ou como você está usando estas informações). Supondo que você tenha uma tela onde no cabeçalho da venda queira mostrar o total dos itens, e abaixo mostre os itens num DBGrid (por exemplo), o uso do SQL exclusivo para fazer o sum pode ser uma opção. Mas também, poderia fazer a totalização criando um procedimento para somar cada item do dataset mostrado no DBGrid (sem o uso do outro SQL) e mostrar em um TEdit ou TLabel. São algumas as opções... Abraços
  20. Mesfistofeles, tenho a impressão que aquele cod_item na tabela vendacli está sobrando. Como você diz, a relação entre elas é feita pelo campo num_venda e aquele campo só faz sentido na tabela de itens mesmo. baseado na relação citada acima, este select não está correto mesmo. Deveria ser: select * from item where num_venda = :num_venda Nem eu sei o que pensar sobre este comentário. Não entendi o que você quiz dizer. Quando você estabelece a relação dos datasets via propriedade DataSource ou MasterSource (depende de que tipo de dataset você usa), é natural que ao mexer o dataset principal (master), o dataset dependente (detail) seja reposicionado (normalmente no início). Assim, para entender melhor este seu último "sentimento", seria necessário saber como voce está "amarrando" os datasets na sua aplicação e que componentes você está usando para a visualização dos dados (se possível uma imagem do layout para uma noção mais correta). Abraços
  21. Seria melhor você postar a estrutura das tabelas. Este SQL está filtrando um item específico.Quando você vai filtrar items de determinada coisa (um pedido, por exemplo), para listar, somar ou fazer qualquer outra coisa com eles, o filtro será pelo "código" desta determinada coisa.
  22. Gabriel Cabral, considerando que você chama o procedimento Verifica_BDE no OnCreate do form principal e lá você não deixa que a exceção seja mostrada, esta pode ser a causa. Se quiser tirar a dúvida, troque esta parte da procedure: ... Finally Registro.Free; End; end; por: ... Registro.Free; Except Registro.Free; Raise; End; end;esta alteração não é a ideal, mas dará condições de você verificar se o erro está realmente ocorrendo neste procedimento. Abraços
  23. Micheus

    Zoom na Imagem

    Vai depender de como você vai querer trabalhar com a imagem. Mas, supondo que você tenha a imagem no tamanho grande, então poderíamos considerar que o máximo zoom, seria a a cópia de parte da imagem no tamanho original. Digamos que você vai mostrar a imagem em um TImage com as dimensões 100x100 e esta sua imagem tem o tamanho 2048x1536. Usando o método CopyRect do Canvas, você pode copiar de um o conteúdo de um canvas para outro. Para der uma idéia de como usar isto, veja esta função que o colega Thales postou há algum tempo. Assim, quando você for aplicar o zoom, estará copiando uma porção menor do retângulo original para dentro do TImagem de visualização. É por ai, veja se consegue avançar. Abraços
  24. Se você dividir a string e criar dois elementos, não resolveria? function representantes(param) { var Idx = param.indexOf("/"); var Parte1 = param.substr(0, Idx -1); var Parte2 = param.substr(Idx +1); var p = document.createElement("p"); var p1 = document.createElement("p"); p.appendChild(document.createTextNode(Parte1)); document.getElementById("maparepresentantes").appendChild(p); p1.appendChild(document.createTextNode(Parte2)); document.getElementById("maparepresentantes").appendChild(p1); }
  25. Vou postar aqui o que postei no seu outro tópico na sessão Banco de Dados (ondo julgo que seja o local mais apropriado a sua dúvida) thiago.mac, por esta parte destacada, poderia entender que você teria formatado seu computador. Isto foi feito?
×
×
  • Criar Novo...