Documente Academic
Documente Profesional
Documente Cultură
y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y
Solucionando problemas de arredondamentos Criando tabelas via SQL Salvar imagem em tabela Paradox Evitar a biblioteca midas.dll Copiar qualquer texto para o Clipboard Avaliar de expresso matemtica Rolagem automtica em ListBox Obter data/hora do prprio EXE Mostrar aviso em forma de hint Sons no alto-falante do micro Acessar tabela DB/DBF no diretrio do EXE Ordenar datas pelo ms em Paradox? Excluir todas as ocorrncias de um caractere de uma string Fazer pesquisa incremental apenas com DBGrid Consulta SQL que usa a data do sistema Obter nomes dos campos de uma tabela Obter path de um Alias do BDE Copiar todos os registros de uma tabela para o Clipboard Copiar um registro de uma tabela para o Clipboard Mudar a cor de um DBEdit dentro de um DBCtrlGrid de acordo com uma condio Fazer pesquisa incremental com DBGrid e Edit Limpar um campo tipo data via programao Implementar um campo auto-incremental via programao Exibir a caixa de dilogo padro de solicitao de senha do banco de dados Usar o evento OnGetText de um TField Verificar, via programao, se Local Share do BDE est TRUE Resolver "Internalerrornear: IBCheck" do Interbase 5.1.1 Server no NT Excluir todos os registros de uma tabela Mudar a coluna ativa em um DBGrid via programao Obter o nmero do registro atual Trabalhar com Filter de forma mais prtica Obter a quantidade de registros total e visvel de uma tabela Gravar fisicamente com Paradox Criar uma tabela (DB, DBF) atravs do seu programa Criar um Alias temporrio atravs do seu programa
fui estudando a questo com carinho e cheguei a algumas concluses que resolveram meus problemas. O modo de arredondamento do Firebird igual ao modo das calculadoras financeiras. J no Delphi o arredondamento leva em considerao se a parte inteira par ou mpar quando a parte decimal termina em 5. Os ECFs tambm calculam como no Firebird. Para resolver as diferenas entre Delphi e Firebird escrevi a funo abaixo (a converso para string resolve alguns problemas de arredondamento do Delphi):
function ExRound(Value: Extended; Decimals: Integer): Extended; var Factor, Fraction: Extended; begin Factor := IntPower(10, Decimals); Value := StrToFloat(FloatToStr(Value * Factor)); Result := Int(Value); Fraction := Frac(Value); if Fraction >= 0.5 then Result := Result + 1 else if Fraction <= -0.5 then Result := Result - 1; Result := Result / Factor; end;
Algumas vezes o Delphi gera uns problemas de arredondamento quando voc faz vrios clculos (especialmente multiplicao e diviso) sem aplicar o arredondamento em cada etapa do clculo. Isto ocorre devido ao modo que o Delphi armazena um valor de ponto flutuante numa varivel. Procure fazer o arredondamento a cada etapa do clculo, exceto se este arredondamento passo-a-passo for prejudicar o resultado do clculo. Sempre que possvel use o tipo Currency para variveis que recebero nmeros reais com at 4 casas decimais. Lembre-se tambm de usar AsCurrency ao acessar valores de campos de DataSets. Use no Firebird campos do tipo NUMERIC(x,y) para armazenar valores financeiros e quantidades, mas tome o cuidado de criar o banco de dados com o dialeto 3, pois no dialeto 1 o tipo NUMERIC poder ser convertido para DOUBLE PRECISION internamente. Exemplos:
Quantidade NUMERIC(9,3) Quantidade NUMERIC(18,3) PrecoNUMERIC(9,2) PrecoNUMERIC(18,2) PrecoNUMERIC(18,4) Desconto NUMERIC(4,2)
Crie campos calculados no banco (COMPUTED BY) j com os devidos ajustes de arredondamento. No Firebird existem alguns problemas de arredondamento tambm, mas geralmente se resolve com CASTs. Veja alguns exemplos: Itens de venda:
ValorDescto NUMERIC(9,2) COMPUTED(CAST(Qtd * PrecoVenda * Descto / 100 AS NUMERIC (9,2))),
Total NUMERIC(9,2) COMPUTED(CAST(Qtd * PrecoVenda ValorDescto AS NUMERIC (9,2))), ValorComissao NUMERIC(9,2) COMPUTED(CAST(Total * Comissao / 100 AS NUMERIC(9,2)))
Contas a receber/recebidas:
Atraso INTEGER COMPUTED ( CASE WHEN Recda = 'N' AND Vencto <CURRENT_DATE THEN CURRENT_DATE - Vencto WHEN Recda = 'S' AND Vencto < DataRecto THEN DataRecto - Vencto ELSE 0 END), ValorJuro NUMERIC(9,2) COMPUTED(CAST(Valor * Juro * Atraso / 100 / 30 AS NUMERIC (9,2))), Total NUMERIC(9,2) COMPUTED(CAST(Valor + ValorJuro AS NUMERIC(9,2))), TotalRecdo NUMERIC(9,2) COMPUTED(CAST(CapitalRecdo + JuroRecdo AS NUMERIC(9,2)))
Enfim, use CASTs no Firebird sempre que fizer clculos envolvendo multiplicao e diviso para que o resultado tenha de fato as casas decimais desejadas. Com estas tcnicas acima resolvi completamente os problemas que eu tinha com relao aos arredondamentos, tanto no Delphi quanto no Interbase ou Firebird. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes Este exemplo foi testado com banco de dados Paradox, porm dever funcionar em vrios outros bancos de dados com pouca ou nenhuma alterao. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Bmp := TBitmap.Create; try Bmp.Assign(Table1.FieldByName('Imagem')); Form1.Canvas.Draw(0, 0, Bmp); finally Bmp.Free; end; end;
Observaes O exemplo acima pinta a imagem diretamente no Canvas do Form1. Uma alternativa mais elegante seria usar um objeto TImage para mostrar a imagem. Para salvar em outros bancos de dados a tcnica usava ser semelhante. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes importante lembrar que a distribuio do arquivo midas.dll est sugeito ao pagamento de licenas para a Borland. Entre em contato com a Borland para saber mais detalhes. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes Alguns componentes possuem mtodos tais como CopyToClipboard() que podem ser usados para copiar dados para a rea de transferncia de forma bastante simples. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes Se voc conhece outro componente queira por gentileza nos informar o endereo da pgina para download. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes A mensagem WM_VSCROLL aceita outros parmetros. Pesquise no Help da API do Windows por WM_VSCROLL para obter mais informaes. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
{ Centraliza verticalmente } X := R.Bottom - R.Top + 1; R.Top := (Screen.Height - X) div 2; R.Bottom := R.Top + X; { Mostra } ActivateHint(R, Msg); Update; { Aguarda } Sleep(Tempo); finally Free; end; end; Exemplo de uso: Aviso('Mensagem de aviso', 5000); { Aguarda 5 segundos }
Observaes Usei este recurso por dois motivos. Primeiro para lembrar os velhos tempos do Clipper (legal!) e em segundo lugar para mostrar um breve exemplo que pode ser ampliado para melhorar as mensagens de dicas (hint) de aplicaes feitas em Delphi. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
OUT $42, AL MOV AL, AH OUT $42, AL end; procedure NoSound; asm IN AL, $61 AND AL, $FC OUT $61, AL end; procedure DoBeep(Freq, Duration: LongWord); begin if Win32Platform = VER_PLATFORM_WIN32_NT then Windows.Beep(Freq, Duration) else begin Sound(1193181 div Freq); Sleep(Duration); NoSound; end; end; Se voc no entendeu as rotinas, eis um resumo:
Sound: Inicia um som com uma determinada freqncia (hertz). NoSound: Interrompe o som iniciado por Sound. DoBeep: Esta rotina verifica se o sistema operacional o Windows NT. Se for, chama a API Windows.Beep. Caso contrrio chama Sound, aguarda e, chama NoSound.
Observaes Pelo menos no meu caso, a maioria dos usurios no possuem computadores munidos de caixas de som. Para estes casos as rotinas acima seriam a soluo se o som for indispensvel. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Soluo: No evento BeforeOpen do Table coloque o cdigo abaixo: procedure TForm1.Table1BeforeOpen(DataSet: TDataSet); begin Table1.DatabaseName := ExtractFilePath(ParamStr(0)); end;
Observaes Este procedimento no dispensa o BDE, mas apenas a criao do Alias. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Soluo: Na funo abaixo, o primeiro parmetro o caractere a ser eliminado e o segundo parmetro a string, donde o caractere ser eliminado. function DeleteChar(const Ch: Char; const S: string): string; var Posicao: integer; begin Result := S; Posicao := Pos(Ch, Result); while Posicao > 0 do begin Delete(Result, Posicao, 1); Posicao := Pos(Ch, Result); end; end; === Exemplo de uso === - Coloque um Edit e um Button. - Programe o OnClick do boto conforme abaixo: procedure TForm1.Button1Click(Sender: TObject); begin Edit1.Text := DeleteChar('"', Edit1.Text); { Exclui aspas } Edit1.Text := DeleteChar('.', Edit1.Text); { Exclui pontos } end;
Observaes Para eliminar vrios caracteres poderamos escrever uma funo que fizesse toda a tarefa numa nica chamada. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
- Ajuste as propriedades do DataSource1: DataSet = Table1 - Ajuste as propriedades do DBGrid1: DataSource = DataSource1 Options -> dgEditing = false ReadOnly = true * Pode tambm ajustar a propriedades Columns para escolher as colunas que sero exibidas. - Na seo private da unit declare: private FTexto: string; - No evento OnCreate do form coloque: FTexto := ''; Label1.Caption := ''; - No evento OnKeyPress do DBGrid1: procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char); begin if Key in [#8, #32..#255] then begin if Key = #8 then { BackSpace } FTexto := Copy(FTexto, 1, Length(FTexto) -1) else FTexto := FTexto + Key; { Posiciona na coluna Nome } Table1.FieldByName('Nome').FocusControl; { Escolhe o ndice e procura } Table1.IndexFieldNames := 'Nome'; Table1.FindNearest([FTexto]); { Mostra o texto procurado } Label1.Caption := FTexto; end; end;
Observaes No nosso exemplo estamos pesquisando atravs do campo "Nome". Para esta pesquisa precisamos de um ndice com este campo. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Preciso fazer uma consulta com SQL que me retorne todos os registros em que o valor de um campo do tipo data seja igual ou anterior dada do sistema. Como fazer? Soluo: Query.Close; Query.SQL.Text := 'select * from Tabela where CampoData <= :Hoje'; Query.ParamByName('Hoje').AsDate := Date; Query.Open;
Observaes Este exemplo foi testado com tabelas Paradox, mas deve funcionar na maioria dos bancos de dados com pouca ou nenhuma alterao. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
List := TStringList.Create; try tbGetFieldNames(Edit1.Text, Edit2.Text, List); Memo1.Lines.Assign(List); finally List.Free; end; end;
Observaes Se a unit em que essa rotina for colocada utilizar as units DB e DBTABLES, as chamadas a DbiInit() e DbiExit() podero ser omitidas. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
permitindo ao usurio colar estes dados em outro aplicativo (ex: MS -Word). Isto possvel? Soluo: Sim. Siga os passos abaixo: - Crie seu form normalmente, colocando DataSource, Table e demais componentes; - Coloque um boto e no evento OnClick deste boto coloque o cdigo abaixo: procedure TForm1.Button1Click(Sender: TObject); const SeparadorCampoValor = ': '; SeparadorCampo = #13#10; { Quebra de linha } SeparadorRegistro = '===========' + #13#10; var S: string; I: integer; begin S := ''; Table1.First; while not Table1.EOF do begin for I := 0 to Table1.FieldCount -1 do S := S + Table1.Fields[I].FieldName + SeparadorCampoValor + Table1.Fields[I].AsString + SeparadorCampo; S := S + SeparadorRegistro; Table1.Next; end; Clipboard.AsText := S; end; Para testar: - Execute este aplicativo; - Clique no boto; - V em outro aplicativo (ex: MS -Word) e mande colar (Ctrl+V).
Observaes CUIDADO! No use este recurso com tabelas grandes, pois poder usar memria demasiadamente. No teste que fiz, o tamanho da string S atingiu 20K e funcionou normalmente. Mas isto pode variar de uma mquina para outra. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
um registro de uma tabela para a rea de transferncia, permitindo ao usurio colar estes dados em outro aplicativo (ex: MS -Word). Isto possvel? Soluo: Sim. Siga os passos abaixo: - Crie seu form normalmente, colocando DataSource, Table e demais componentes; - Coloque um boto e no evento OnClick deste boto coloque o cdigo abaixo: procedure TForm1.Button1Click(Sender: TObject); const SeparadorCampoValor = ': ' ; SeparadorCampo = #13#10; { Quebra de linha } var S: string; I: integer; begin S := ''; for I := 0 to Table1.FieldCount -1 do S := S + Table1.Fields[I].FieldName + SeparadorCampoValor + Table1.Fields[I].AsString + SeparadorCampo; Clipboard.AsText := S; end; Para testar: - Execute este aplicativo; - Clique no boto; - V em outro aplicativo (ex: MS -Word) e mande colar (Ctrl+V).
procedure TForm1.DBCtrlGrid1PaintPanel(DBCtrlGrid: TDBCtrlGrid; Index: Int eger); begin ifTable.FieldByName('NomeDoCampo').AsFloat< 0 then DBEdit1.Font.Color := clRed else DBEdit1.Font.Color := clBlue; end;
Observaes Neste exemplo mudamos a cor da fonte do componente DBEdit, Porm, pode-se tambm mudar a cor do prprio componente (DBEdit1.Color). Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Altere as seguintes propriedades: DataSource1.DataSet = Table1 Table1.DatabaseName = 'NomeDoAlias' Table1.TableName = 'NomeDaTabela' Table1.IndexFieldNames = 'NomeDoCampo' Table1.Active = true DBGrid1.DataSource = DataSource1
Observaes Este exemplo considera que o campo seja tipo string. Para outros tipos de campos pode ocorrer erro dependendo dos valores digitados no Edit1.
Observaes Podemos usar este recurso para limpar tambm campos numricos, string, etc. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes A funo acima incrementa o campo somente se estiver vazio. Assim podemos dar ao usurio a opo de digitar neste campo ou deix-lo vazio para que seja autoincrementado. Existem vrias outras formas de implementar este recurso. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes As senhas adicionadas nesta caixa de dilogo so adicionadas na sesso (TSession) atual. Isto til quando colocamos senha em tabelas Paradox, ou mesmo quando trabalhamos com banco de dados Client Servidor, e queremos que o usurio digite a senha de acesso. Se no fizermos desta forma, nem adicionarmos via programao as senhas necessrias, esta caixa de dilogo ser mostrada quando o programa tentar abrir uma tabela com senha. A grande vantagem aqui que podemos traduzir os Caption's dos componentes. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br
Incio
Observaes Ao exibir ser exibido os nomes. Mas ao digitar continue com os 1, 2, 3, etc. Para usar este recurso em relatrios, acesse a propriedade DisplayText em vez de AsString para obter o valor do campo. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes A funo acima faz a verificao no registro do Windows. Por isto est sujeita a falha caso o BDE coloque as configuraes em outro local ( o caso do BDE salvar as configuraes no formato do Windows 3.x). O ideal seria usar uma API do BDE, mas at o momento no conheo uma que retorne esta informao. Caso algum saiba, queira por gentileza nos informar. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Anote est soluo, muitos tem o mesmo problema mas no conseguem a soluo to facilmente como eu. Look: Problema: Estou com um problemo. Trabalho com o NT 4 workstation Service Pack 3, Delphi 3 e Interbase 4.2.xxx. E instalei o Interbase 5.1.1 Serve r nesta mquina. At a tudo bem. Quando fui rodar a aplicao deram alguns problemas de converso do tipo de Dado. Analisando o problema percebi que havia esquecido de instalar o Client do Interbase. Foi a que comearam os problemas. Tentei instalar o client, porm o instalador aps preparar os arquivos de instalao mostrava a seguinte mensagem e parava : Titulo da janela = "Severe", mensagem = "Internalerrornear: IBCheck"; comecei a ler os manuais, em certo ponto aconselhava desinstalar qualquer verso posterior do Interbase da minha mquina. Foi ento que desinstalei o Interbase 4.2.xxx (atravs do "ControlPanel", "Add/Remove Programs"). Nova tentativa de instalar o client, o erro persistia. Resolvi desinstalar (atravs do "Control Panel", "Add/Remov e Programs") todo o Interbase da minha mquina e comear tudo de novo. Porm quando tentei instalar novamente o Interbase Server, surpresa, o erro apareceu novamente. Mas agora no havia interbase instalado. Fui desinstalando Delphi, BDE, ... e nada. Entr ei no Regedit, pois o desinstalador, normalmente, faz o trabalho incompleto e necessrio excluir um monte de lixo do Registry. Deparei com a seguintes chaves: hkey_local_machine \system\controlset001 \enum\root\legacy_interbase_gua rd hkey_local_machine \system\controlset001 \enum\root\legacy_interbase Tentei exclu -las, porm so chaves protegidas, e o regedit no permitiu que eu exclusse -as. Poderiam me dar uma soluo para eu poder instalar o Interbase em minha mquina? Preciso disto com urgncia. Obrigado, Alexsandro Pimenta Xenon Software Comrcio e Servios Ltda apepper@uol.com.br Soluo: Sr. Alexsandro, Esse erro: 'Internalerrornear: IBCheck' acontece apenas em algumas mquinas NT 4. Na hora da instalao, criada uma chave com valor errado.
Entre no registry do Windows e altere a opo, PATH de binrio para string, da chave: HKEY_CURRENT_USER \Environment
Observaes Se houver um filtro ou range ativo, somente os registros filtrados sero excludos. Portanto diferente de Table1.EmptyTable. Esta funo poder ser chamada no evento BeforeDelete do Table (ou Query) principal em um formulrio mestre-detalhe para excluir os itens (da parte detalhe). Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Observaes Aconselho usar o nome do campo quando o que importa o campo e no a posio. Use o nmero da coluna somente quando o que importa a posio, e no o campo. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br
Incio
Observaes A funo QuitedStr() coloca apstrofos envolvendo a string. Se houver um apstrofo como parte da string, ela o subtitui por dois apstrofos, para que seja corretamente interpretado. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Table1.Filtered := true; Se quizermos obter a quantidade total de registros, independentemente de filtros, devemos usar uma API do BDE conforme abaixo: var Total: integer; begin Check(DbiGetRecordCount(Table1.Handle, Total)); ShowMessage('Total de registros: ' + IntToStr(Total)); end;
Observaes Para testar o exemplo acima, o Table1 precisa estar aberto. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Tabela.TableName := 'Clientes.DB'; Tabela.TableType := ttParadox; { ou ttDBase } { Somente Delphi4 } ifTabela.Existsthen { Se a tabela j existe... } Exit; {***} { Cria a tabela } Tabela.FieldDefs.Add('Codigo', ftInteger, 0, true); Tabela.FieldDefs.Add('Nome', ftString, 30, true); Tabela.FieldDefs.Add('DataNasc', ftDate, 0, false); Tabela.FieldDefs.Add('RendaMes', ftCurrency, 0, false); Tabela.Field Defs.Add('Ativo', ftBoolean, 0, true); { etc, etc, etc } Tabela.CreateTable; { Cria os ndices } Tabela.AddIndex('ICodigo', 'Codigo', [ixPrimary, ixUnique]); Tabela.AddIndex('INome', 'Nome', [ixCaseInsensitive]); { etc, etc, etc } finally Tabela.Free; end; end;
Observaes Para verificar se o arquivo j existe na verso 3 ou anterior do Delphi, voc dever usar a funo "FileExists" do Delphi. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio
Estou usando os componentes: SQLQuery, DataSetProvider, ClientDataSet e DataSource para manipular os dados, delphi 7 e Firebird.