Ir para conteúdo
Fórum Script Brasil

Micheus

Veteranos
  • Total de itens

    3.189
  • Registro em

  • Última visita

Tudo que Micheus postou

  1. Que bando de dados você está utilizando? Se sua chave primária é um Integer e você espera que receba um valor automaticamente, parece que não estamos falando de um campo de numeração automática, então, aonde é que você o define/calcula? Em uma trigger, no evento BeforePost,...?
  2. A pergunta é:quando você diz que sai apenas uma única página, você está querendo dizer algo tipo, clicar no botão relatório e impremir apenas os dados destas variáveis? Não haveria uma sequência de páginas com as mesmas informações recalculadas, assim como quem lista os dados de uns 10 clientes, por ex.?Bom, se for, então não utilize o BeforePrint para calcular os valores e atribuí-los aos QRLabels. Faça tudo isso antes da chamada a QuickRe.Preview; Uma coisa a ser considerada, ao criar qualquer relatório com o QuickReport é que, ao utilizar o Preview (99,99% dos casos utilizamos), quando é acionado o comando de impressão, todo o relatório é novamente gerado - ou seja, reprocessado, deste modo tudo é executado duas vezes da visualização até a impressão final. Na situação que citei inicialmente, você estará preparando ele, antes mesmo da visualização. Deste modo, quando da visualização e/ou impresso, nenhum processamento extra é realizado. é claro que é só um pedaço...hehehe....é grande o codigo para limpar as variaveis. Aqui você poderia otimizar sim. Eu não teria o trabalho de inicializar 90 variáveis uma-a-uma ( :blink: haja paciência, não dá nem para copiar/colar). Vai uma dica: declare um record contendo todas as suas variáveis, depois simplesmente inicialize elas com um simples:FillChar(RecVariaveis, SizeOf(RecVariaveis), 0); Prontinho ;) Abraços
  3. Que componentes você pretende utilizar? Voce pode utilizar datasets do tipo Query ou Table. A escolha pode em alguns casos depender do fato de você vir a colocar ou não o dataset em edição.Se quiser citar nome de campos, isso facilita uma exemplificação.
  4. Fiz uns testes aqui e não tive qualquer problema. Defini a propriedade MaxPointPerPage = 3, utilizei um dataset com 11 itens e funcionou perfeitamente.você está conseguindo ver o gráfico? Em design-time você consegue utilizar a pré-visualização das páginas na guia Paging (duplo click no DBChart - botões com setas esquerda, direita, ...)? Isto é relativamente simples. Depende do lay-out do seu relatório.1) Se será impresso apenas o gráfico (um único gráfico). Voce pode colocar em um QuickRep uma banda Title para adicionar os items que você queira mostrar (dados diversos) e uma banda detail aonde você colocará seu componente TQRChart. Não vincula qualquer dataset a respectiva propriedade do QuickReport. a. você define uma variável global no form, do tipo inteira, (tipo em private - ex. QtdPag :integer) para conter o número de páginas do gráfico; b. antes de chamar o Preview do Quickreport, você calcula o nº de páginas que seu gráfico tem: procedure TForm1.VisualizaGrafico; begin // se as séries tiverem que ser inicializadas na mão, este é o local aonde deve ser feito QtdPag := QRChart1.Chart.Series[0].Count div QRChart1.Chart.MaxPointsPerPage; if (QRChart1.Chart.Series[0].Count mod QRChart1.Chart.MaxPointsPerPage) > 0 then Inc(QtdPag); QuickRep1.Preview; end; c. no evento BeforePrint (QuickRep) você posiciona na primeira página do Chart. Com isso ao visualizar ou imprimir, você garante que a impressão do gráfico comece no início:procedure TForm1.QuickRep1BeforePrint(Sender: TCustomQuickRep; var PrintReport: Boolean); begin QRChart1.Chart.Page := 1; end; d. no evento OnNeedData (QuickRep) você informa até quando o relatório será impresso, ou seja, enquanto todas as páginas do gráfico não tiverem sido impressas:procedure TForm1.QuickRep1NeedData(Sender: TObject; var MoreData: Boolean); begin MoreData := QRChart1.Chart.Page < QtdPag; end; e. no evento AfterPrint (banda Detal), após a impressão da página do Chart atual, você avança a página:procedure TForm1.QRSubDetail1AfterPrint(Sender: TQRCustomBand; BandPrinted: Boolean); begin QRChart1.Chart.NextPage; end; 2) Se for para imprimir várias páginas de gráficos para cada item listado na banda detalhe (vários itens em uma consulata), o procedimento é parecido. Neste caso, teremos um dataset vinculado a respectiva propriedade do QuickReport, na banda Detail você terá os dados provenientes deste dataset. Então, utilizaremos uma banda SubDetail para fazer o processo similar ao item 1: a. você define uma variável global no form, do tipo inteira, (tipo em private - ex. QtdPag :integer) para conter o número de páginas do gráfico; b. no evento BeforePrint (banda Detail) você determina a quantidade de páginas que o Chart tem e posiciona na primeira página do mesmo. Com isso, a cada banda impressa, você garante que a impressão do gráfico comece no início:procedure TForm1.QRBand1BeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean); begin // se as séries tiverem que ser inicializadas na mão, este é o local aonde deve ser feito QtdPag := QRChart1.Chart.Series[0].Count div QRChart1.Chart.MaxPointsPerPage; if (QRChart1.Chart.Series[0].Count mod QRChart1.Chart.MaxPointsPerPage) > 0 then Inc(QtdPag); QRChart1.Chart.Page := 1; end; c. no evento OnNeedData (banda SubDetail) você informa até quando o relatório será impresso, ou seja, enquanto todas as páginas do gráfico não tiverem sido impressas:procedure TForm1.QRSubDetail1NeedData(Sender: TObject; var MoreData: Boolean); begin MoreData := QRChart1.Chart.Page < QtdPag; end; d. no evento AfterPrint (banda SubDetail), após a impressão da página do Chart atual, você avança a página:procedure TForm1.QRSubDetail1AfterPrint(Sender: TQRCustomBand; BandPrinted: Boolean); begin QRChart1.Chart.NextPage; end; Tudo isso assumindo que a quantidade de itens de cada série é a mesma, do contrário, você terá que saber qual o maior número de itens para atribuir à QtdPag. Eu não consegui vincular o meu dataset ao TQRChart, então movi valores na mão (parece-me um bug), mas isso não influenciará em nada, apenas que se você passar pelo mesmo problema... Abraços
  5. Micheus

    Relatorio

    Pirambu!, utilizando as 3 queries, tente seguir esses passos e acho que você consegue mostrar corretamente suas informações. Utilize o dataset do Lancamento vinculado ao seu QuickReport (propriedade Dataset), na banda detalhe coloque os campos referentes ao lançamento. As consultas para Pecas e Servicos, você coloca na cláusula WHERE o campo de vínculo da tabela sendo igual a um parâmetro que, neste caso, como queremos que seja o valor vindo da tabela principal (Lancamento), tenha o nome do respectivo campo. No seu caso seria: ... WHERE Num_lancID = :Num_lancID ..., onde o parâmetro Num_lancID é o nome do campo que obteremos da tabela lancamento. Para que funcione este recurso, utilizamos um DataSource ligado ao dataset Lancamento. Então, nos dataset's Pecas e Servicos, apontamos a propriedade DataSource para o este DataSource recém adicionado. Deste modo, quando você abrir as consultas, os parâmetros que não forem informados manualmente, serão procurados neste dataset vinculado - por isso o parâmetro ter o nome do campo deste dataset. No relatório, você adiciona duas bandas tipo SubDetail, uma para cada consulta (Pecas e Servicos) e adiciona os respectivos campos. Antes do preview do relatório, você abre as duas consultas - após o dataset principal estar posicionado é claro. Se não me engano é isto.
  6. Carlos Rocha, dá uma olhada neste post, acho que responde sua pergunta. Abraços
  7. Pirambu!, baseado no que coloquei no post anterior, segue uma função para implementar o recurso sobre os itens do menu (ela pode ser colocada em um unit de utilidades - não está vinculada a um form): // Procedimento recursivo para "mapear" todos os itens do menu procedure SetMenuAccess(Menu :TMenuItem; AccessLevel :Integer); var Idx :Integer; begin for Idx := 0 to Menu.Count -1 do begin // habilita ou não item conforme nível de acesso configurado Menu.Items[Idx].Enabled := Menu.Items[Idx].Tag <= AccessLevel; // apenas se habilitado é que processa os sub-menus if Menu.Items[Idx].Enabled then SetMenuAccess(Menu.Items[Idx], AccessLevel); end; end; Como você vê, é um sistema bastante simples. Para facilitar os testes, um exemplo para download. Nele utilizei os níveis de 0 a 2, bem como utilizo a propriedade Enabled - o usuário vê a opção, mas não o acessa. Se trocar por Visible, então não estará visível a opção conforme nível selecionado. Abraços
  8. Pelo que entendo até deveria ter, mas não consegui fazer funcionar até hoje. A função StrFloat tem um overload que permite que seja passados os parâmetros de formatação:function StrToFloat(const S: string; const FormatSettings: TFormatSettings): Extended; overload; Supostamente, se obtermos as formatações da localidade (conf. do windows), e passarmos a função, ela deveria fazer a conversão corretamente. Ex.: var Valor :Extended; FrmtSetting :TFormatSettings; begin GetLocaleFormatSettings(LOCALE_USER_DEFAULT, FrmtSetting); Valor := StrToFloat(Edit1.Text, FrmtSetting); ... Só que não dei jeito não. :angry: Tenta utilizar esta função:function StrValueToFloat(Value :string) :Extended; begin while Pos('.', Value) > 0 do Delete(Value, Pos('.', Value), 1); Result := StrToFloatDef(Value, 0); end; O uso de StrToFloatDef é só para garantir um 0.00 quando o string for nulo. Abraços
  9. Pirambu, é só seguir a mesma lógica:- para achar o nulo você usou IS NULL; - então, para achar no não nulo você usa IS NOT NULL. ex. where Data is not null ou where not (Data is null)
  10. Micheus

    Dúvidas Sobre Skins

    Hudson, siga as instruções do colega Bruno Souza (post anterior ao seu), ou seja, envie um e-mail a ele que você recebe o componente. ;) A propósito, o VCLSkin não é FREE (veja Order VCLSkin) - o que você vai estar recebendo é, muito provavelmente, uma versão "crackeada"!!! Abraços
  11. Micheus

    Apagando Valor

    Como posso resolver este problema? Eu lhe sugeriria, como maneira correta de fazer esse tipo de atribuição, utilizar o campo do dataset ligado ao seu TDBEdit e não o componente. Exemplificando... Supondo que o dataset ligado aos componentes TDBEdit seja TbCliente, você faria deste modo: DmDados.TbClienteEND.Value := DmDados.QrCEPLOGRADOURO.Value; DmDados.TbClienteBAIRRO.Value := DmDados.QrCEPBairro.Value; DmDados.TbClienteCIDADE.Value := DmDados.QrCEPCidade.Value; Abraços
  12. Tente baixar este do Torry's: http://www.torry.net/vcl/packs/huge/rx275d2005.zipNão sei se instala fácil, dê uma olhada no Readme.txt - não tenho o D2005 para testar. Abraços
  13. Micheus

    Update

    Ruyfreis, como você configurou sua transação (propriedades) - duplo click no componente IBTransaction? Se foi selecionando via radiobox Read Commited, observe que na caixa Settings existem 3 linhas, cada qual com uma opção. Inclua a opção Read - se não estou enganado poderá resolver. Eu fiz algo assim há um tempo atrás, mas como meu micro está encaixotado temporariamente (até fim do mês - coisa de reformas no ap) não tenho como conferir, mas acredito o caminho seja por aí. ;) De qualquer modo, dê uma olhada neste artigo, ele deverá lhe ajudar a fazer as alterações necessárias para que isso não ocorra. Inclusive, você não precisa testar necessariamente em rede, basta que você abra duas instâncias do programa em sua máquina para os testes. Abraços
  14. Bom, a situação que citei seria no sentido de definição de níveis de segurança. Uma ilustração hipotérica, seria assim:Nivel 1 - acesso mínimo Nivel 2 - acesso intermediário (equivale ao Nivel 1 + alguns itens) Nivel 3 - acesso total (equivale ao Nivel 1, Nivel 2 e todo o resto) daí, na tag dos itens do menu, form, botões (o que quer que seja controlado) você define qual o nível que acessa aquela opção. Na informação do usuário você teria a indicação sobre qual nível de acesso esse usuário tem. Por exemplo, um usuário tipo administrador teria Nivel 3 de acesso. Já um mais restrito poderia ter Nivel 1. Em termos de programação da interface, poderia ser implementado de várias maneiras. Por exemplo, ao ser clicado em um item de menu, antes da execução do código principal no procedimento, poderia ser verificado o nível de acesso do usuário comparado com o definido na tag de modo a permitir a continuidade ou não. Vou tentar exemplificar: procedure TForm1.MnuCadastroClick(Sender :TObject); begin if Nivel_Usuario < (Sender as TMenuItem).Tag then begin ShowMessage('Você não possui autorização para acessar esta função!'); Exit; // Encerra execução do procedimento end // segue com o código normalmente ... end; Mas também, você poderia, após validar o usuário, varrer seus itens de menu e ocultá-los caso o nível de acesso do usuário fosse inferior ao valor da tag dos mesmos e, neste caso, não seria necessário fazer as validações como no exemplo anterior. Abraços
  15. Alessandro, a idéia proposta é criar uma função genérica (poderia ser colocada em uma unit de utilidades), mas que neste caso, serve apenas para uso com Zeos e MySQL (a idéia pode ser facilmente adaptada à outros). A primeira sugestão é específica para MySQL, pois faz uso de tabela de sistema do banco (há similares em outros bancos - questão de adaptação): function CheckField(Connection :TZConnection; TableName, FieldName :string) :boolean; var QryCheck :TZQuery; begin Result := False; QryCheck := TZQuery.Create(nil); QryCheck.Connection := Connection; QryCheck.SQL.Add('SELECT COLUMN_NAME'); QryCheck.SQL.Add('FROM INFORMATION_SCHEMA.COLUMNS'); QryCheck.SQL.Add('WHERE table_name = '''+TableName+''''); try QryCheck.Open; Result := QryCheck.Locate('COLUMN_NAME', FieldName, [loCaseInsensitive]); QryCheck.Close; finally QryCheck.Free; end; end; A segunda opção, mas fácil de ajustar para outros bancos, seria utilizar um TZQuery e fazer um SELECT que ao abrir a query resultará nos campos existentes na tabela. Para evitar tráfego de muitas informações na rede, poderíamos fazer uso da instrução LIMIT presente na sintax do SELECT no MySQL, já que nosso objetivo não seria a obtenção dos dados mas sim o nome dos campos. Deste modo, após o open da query você terá na propriedade Fields todos os campos constantes da tabela e poderá procurar pelo que você deseja saber se existe ou não. Ficaria assim:function CheckField(Connection :TZConnection; TableName, FieldName :string) :boolean; var QryCheck :TZQuery; begin Result := False; QryCheck := TZQuery.Create(nil); QryCheck.Connection := Connection; QryCheck.SQL.Add('select * from '+TableName+' limit 0'); try QryCheck.Open; Result := Assigned(QryCheck.FindField(FieldName)); QryCheck.Close; finally QryCheck.Free; end; end; exemplo de uso da função:... if CheckField(ZConnection1, 'usuario', 'nome') then ShowMessage('Ok') else ShowMessage('Não existe!'); ... Abraços
  16. Micheus

    Update

    Que componentes você está utilizando para a conexão? Como está configurada a transação (readcommited, ...)? Pode ser algo relacionado a como você utiliza as transações. Já deu uma conferida nisto? Abraços
  17. Esta propriedade existe em todos (ou quase) os componentes.É uma propriedade do tipo LongInt, assim, você pode armazenar qualquer coisa que caiba neste campo (que não ultrapasse os 4 bytes). Pode ser um endereço de memória, caracter, byte, ... (basta fazer um type-cast). Utiliza-se para muitas coisas, vai do "gosto do freguês" :). Já vi casos em que é utilizada para indicar nível de acesso em controle deste tipo nas aplicações. Eu costumo utilizá-lo em botões Novo, Alterar e Excluir (0, 1 e 2 respectivamente) para utilizar o mesmo evento OnClick e tratar cada função dentro do procedimento do evento - se interessar veja neste tutorial em Procedure TCadTesteDBEdit.BtnNovoClick(Sender: TObject);. Minha contribuição seria essa. Abraços
  18. Foi!!! Não, porque você não tinha deixado claro que era este o formato, mas podemos trabalhar nele, apesar que não vai dar para fugir muito do recurso que você utilizou. Vou ter que dar uma olhada, mas eu sei que existe um pacote que extende funções do QuickReport que, se não me engano, teria algum componente que poderia ser utilizado para contornar esta situação. Abraços
  19. Eu até estou acostumado a ouvir deste modo, mas escrito, eu ainda prefiro Micheus. ;) Acho que não procede. Observe que o exemplo que postei utiliza tabela paradox e o código para inicializá-la no relatório é:procedure TForm1.PrintPreview; begin // limpa a query original, adicionada ao componente para // viabilizar criação dos campos em design-time QryMeses.SQL.Clear; QryMeses.SQL.Add('select Ano, mês, SUM(Valor) as Valor'); QryMeses.SQL.Add('from totais.db'); QryMeses.SQL.Add('where Ano = :ano'); QryMeses.SQL.Add(' and Cliente = :cliente'); { // outros filtros podem ser incluído aqui QryMeses.SQL.Add(' and campo = :parametro'); ... } QryMeses.SQL.Add('group by Ano, mês'); QryMeses.SQL.Add('order by Ano, mês'); Query1.Open; QuickRep1.Preview; end; Não abriu o anexo ou o projeto? O projeto foi feito em D3 (é o que eu tinha na hora) mas nunca tive problema em abrir um deles no D7. :huh:Se o problema foi com o anexo, tente baixar deste link. Se for com o projeto, exclua os arquivos .dof e .dsk - deve funcionar. Abraços
  20. Opa Então Micheus, sobre o SelStart parece ser uma boa, se der pra salvar a posição do cursor então acredito que de pra fazer o que ele quer em eventos como onKeyUp... Isto mesmo. O que tenho, descende de TEdit. Não no Style mesmo. Veja uma pontinha do código:procedure TAlignedEdit.CreateParams(var Params: TCreateParams); const AlignOnAPI: array [TAlignment] of DWORD = (ES_LEFT, ES_RIGHT, ES_CENTER); begin inherited CreateParams(Params); // adicionamos Multiline ao estipo para que possa ser aplicados // os alinhamentos à Direita e Centralizado - ver help CreateWindow // ES_RIGHT e ES_CENTER if FEditType <> etText then Params.Style := Params.Style or ES_MULTILINE or AlignOnAPI[FAlignment]; // se o edit ler números inteiros, então definimos para aceitar apenas // caracteres numéricos if FEditType = etInteger then Params.Style := Params.Style or ES_NUMBER; end; Abraços
  21. É isto mesmo Churc e o meio de impedir que isso ocorra é salvar a posição do cursor (propriedade SelStart do edit) antes da alteração e ajustar sua posição caso seja realizada alguma alteração no sentido de incluir os caracteres de pontuação da formatação. Tem outra coisa em questão ainda, para definir o alinhamento do edit para outra que não a esquerda, faz-se necessário manipular a criação do componente, visto que é necessário definir em seu estilo que tráestá-se de um componente multi-linha, bem como o tipo do alinhamento (ver comentário no help Win32API - CreateWindow - EM_RIGHT). Disto resulta que a melhor saída seria realmente utilizar/criar um componente para este fim (minha opnião). Em meu componente (mencionado anteriormente), eu utilizo o evento OnKeyPress, mas é um controle chato de ser feito (pelo menos ainda não consegui deixar redondo). Deve ser observado também, a questão de modificar a propriedade Text, como resultado do processamento, pois resultará na ocorrência de um evento OnChange (se não me falha a memória). Neste caso, faz-se necessário ainda salvar e remover o evento (atribuir nil a OnChange) e restaurá-lo depois do processamento - isso no caso de haver qualquer processamento no referido evento. Abraços
  22. Voce está correto Churc. O componente está na paleta RX Controls e para a função que o colega pretende fazer dele, é necessário habilitar (deixar true) a propriedade FormatOnEdit. A formatação é definida através da propriedade DisplayFormat. Entretanto, este é um componente tipo TEdit - não tem uma versão DataWare, ou seja, que possa ser ligado a um campo de um dataset. A medida que o tempo permita, eu comecei adaptar um componente que eu tenho, que simplesmente posibilita o alinhamento de números pela direita (TAlignedEdit), para que possa ser utilizado como um DataWare já que achei a idéia interessante. Qualquer hora dessas, eu posto aqui. ;) Abraços
  23. Duas opções: 1) utilizar RxLib (unit RxHints) - exemplo no DevMedia; ou 2) Utilizar API do Windows - exemplo no Planeta Delphi (tem que se registrar - vale a pena). Abraços
  24. Micheus

    Delphi Para Sql

    João, você não respondeu o questionamento do Churc com relação ao componente utilizado. <_< Entretanto, vou exemplificar utilizando o componente TStoredProc. Esta sua procedure no banco, deve estar codificada para receber o tal parâmetro, certo?! Então, tendo você adicionado este componente no seu programa, ajustado a propriedade DataBaseName, você seleciona na propriedade StoredProcName a sua procedure. A seguir, clica no botãozinho "..." na propriedade Params, deve estar listado o(s) parametro(s) que a sua procedure espera receber. Verifique a caixa Parameter Type, que deve (provavelmente) ser/estar setada para Input. Depois, no código do seu botão, você coloca algo como: ... StoredProc1.ParamByName('nome_parametro').Value := valor_parametro; try StoredProc1.ExecProc; except // trata o erro aqui end; end; Abraços
  25. Progr'amador, se o Eder, controlar a impressão na mão não ficaria mais simples, talvez? Se entendí direito, ele está listando para cada item em Query1, os totais mensais - todos os meses do ano (12) - independente de haverem registros ou não. Se for isso, acho que daria para, mantendo ligada a query1 ao quickrep cujos dados estariam na banda Detail, adicionar uma banda do tipo SubDetail (controlando sua impressão na mão, via evento OnNeedData) para impressão dos valores mensais. O uso de bandas Header e Footer ligadas a SubDetail controlariam os totalizadores. Não seria necessário utilizar UNION, ao invés disto utilizaríamos com GROUP BY. Segue um exemplo em anexo para verificação. Abraços QuickRep___Detail_SubDetail.zip
×
×
  • Criar Novo...