Ir para conteúdo
Fórum Script Brasil

Micheus

Veteranos
  • Total de itens

    3.189
  • Registro em

  • Última visita

Tudo que Micheus postou

  1. Micheus

    agenda

    andre_seco, vejo que você está bastante crú na programação Delphi - siga lendo mais. ;) Tentando explicar a função de QuotedeStr naquela linha: A função QuotedeStr tem como objetivo colocar o texto '25/12/2008' com aspas simples dentro da string do SQL. Como o Delphi usa a aspa simples ('), como delimitador de string, ao introduzir este caracter em uma string do delphi, você tem que sinalizar ao compilador que você não está terminando a sua string, mas sim querendo usar nesta string o caracter ('). Como facilitador, foi criada esta função para que não gere muita confusão e evite erros. Mas seria possível fazer a mesma coisa sem usar a função, simplesmente repetindo o caracter (') 2 vezes: AdoQueryConsulta.SQL.Add('exec dba.ConsultaHorario ''25/12/2008'',1'); Observe que as aspas simples vermelhas são o delimitador da string, e que onde deverá aparecer as aspas simples no texto, colocamos duas aspas simples seguidas - no resultado a data estará entre aspas simples. Sabido isto, para você consultar outras semanas, você terá que mudar aquela data que está lá! Assim, ao invés de você colocar fixa a data, você tem que usar aquela que será selecionada no componente TDateTimePicker: AdoQueryConsulta.SQL.Add('exec dbo.ConsultaHorario ' + QuotedStr(DateTimePicker1.Data) + ',1'); Eu acredito que você poderia utilizar, também, a versão com parâmetro: AdoQueryConsulta.SQL.Add('exec dbo.ConsultaHorario :Data,1'); AdoQueryConsulta.Params.ParamByName('Data').Value := DateToStr(DateTimePicker1.Data); Abraços
  2. acho que posso "palpitar" neste... pela lógica, o valor que você quer é aquele que é dividido pelo valo total de votos => $lines[$i][1]. <?php clearstatcache(); // limpa o cache : : // controi uma tabela com o resultado parcial da enquete echo "<strong>:: Resultado parcial</strong></p><hr>"; echo "<p><table><tr><td>" . $question . "</td></tr>"; for( $i = 2; $i <= $nlines; $i++) { $qtdvotos = $lines[$i][1]; // quantidade de votos para a opção i echo "<tr><td>" . $lines[$i][0] . "</td>"; // imprime a opção i echo "<td>"; // imprime a quantidade formatada printf(" %d", $qtdvotos); // me parece estar faltando aqui o fechamento das tags td e tr => echo "</td></tr>"; } echo "</table>"; echo "<br>Total de votos <strong>" . $soma . "</strong> até o momento</p>"; ?>
  3. António44, você não comentou antes qual o erro e eu não "antenei" neste detalhe que não é aceito pelo D3: - a definição do valor default para a constante User Considerando que seria interessante você fazer a modificação para uso do seu programa apenas, seria conveniente que, ao finalizar o programa, você retornasse a variável ao seu estado inicial. Assim, vou postar a função corrigida e outros códigos complementares que implementei naquele meu projeto em Delphi3: uses Registry; // unit com a declaração de TRegistry // função para mudança de variáveis de ambiente function SetGlobalEnvironment(const Name, Value: string; const User: Boolean): Boolean; resourcestring REG_MACHINE_LOCATION = 'System\CurrentControlSet\Control\Session Manager\Environment'; REG_USER_LOCATION = 'Environment'; begin with TRegistry.Create do try if User then { User Environment Variable } Result := OpenKey(REG_USER_LOCATION, False) else { System Environment Variable } begin RootKey := HKEY_LOCAL_MACHINE; Result := OpenKey(REG_MACHINE_LOCATION, False); end; if Result then begin WriteString(Name, Value); { Write Registry for Global Environment } { Update Current Process Environment Variable } SetEnvironmentVariable(PChar(Name), PChar(Value)); { Send Message To All Top Window for Refresh } SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PChar('Environment'))); end; finally Free; end; end; { SetGlobalEnvironment } // função para obtenção do valor de variáveis de ambiente function GetGlobalEnvironment(const Name: string; const User: Boolean): string; resourcestring REG_MACHINE_LOCATION = 'System\CurrentControlSet\Control\Session Manager\Environment'; REG_USER_LOCATION = 'Environment'; var Resultado :Boolean; begin with TRegistry.Create do try if User then { User Environment Variable } Resultado := OpenKey(REG_USER_LOCATION, False) else { System Environment Variable } begin RootKey := HKEY_LOCAL_MACHINE; Resultado := OpenKey(REG_MACHINE_LOCATION, False); end; if Resultado then Result := ReadString(Name); finally Free; end; end; { GetGlobalEnvironment } procedure TForm1.FormCreate(Sender: TObject); var TMP, WinDir :String; begin TMPOld := ''; // variável declarada na sessão private do form WinDir := GetGlobalEnvironment('windir', False); // o código abaixo só irá funcionar no Windows XP e superior, abaixo destes // não deve haver problemas com nomes longos if WinDir = '%SystemRoot%' then begin TMP := GetGlobalEnvironment('TMP', False); Delete(TMP, 1, Length(WinDir)); TMPOld := GetGlobalEnvironment('TMP', True); if not SetGlobalEnvironment('TMP', 'c:\windows'+TMP, True) then ShowMessage('Não foi possível alterar a variável de ambiente "TMP"'); end; end; procedure TBrwChaves.FormDestroy(Sender: TObject); begin if TMPOld <> '' then // se variável foi alterada... SetGlobalEnvironment('TMP', TMPOld, True); end; Mas, no caso específico da variável de ambiente que armazena o caminho da pasta temporária (TMP), segue uma versão enxuta e que não muda o path padrão - apenas altera-a para conter o caminho curto (short path) fazendo uso da função da API GetShortPathName: uses Registry; // unit com a declaração de TRegistry // função para mudança de variáveis de ambiente function SetGlobalEnvironment(const Name, Value: string; const User: Boolean): Boolean; resourcestring REG_MACHINE_LOCATION = 'System\CurrentControlSet\Control\Session Manager\Environment'; REG_USER_LOCATION = 'Environment'; begin with TRegistry.Create do try if User then { User Environment Variable } Result := OpenKey(REG_USER_LOCATION, False) else { System Environment Variable } begin RootKey := HKEY_LOCAL_MACHINE; Result := OpenKey(REG_MACHINE_LOCATION, False); end; if Result then begin WriteString(Name, Value); { Write Registry for Global Environment } { Update Current Process Environment Variable } SetEnvironmentVariable(PChar(Name), PChar(Value)); { Send Message To All Top Window for Refresh } SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PChar('Environment'))); end; finally Free; end; end; { SetGlobalEnvironment } procedure TBrwChaves.FormCreate(Sender: TObject); var LongPath :array[0..512] of char; ShortPath :array[0..MAX_PATH] of char; begin GetTempPath(SizeOf(LongPath), LongPath); if LongPath <> '' then begin if GetShortPathName(LongPath, ShortPath, MAX_PATH) > 0 then begin if not SetGlobalEnvironment('TMP', ShortPath, True) then ShowMessage('Erro ao tentar mudar a variável de ambiente "TMP"'); end else ShowMessage('Erro ao obter o path curto.'); end; end; Abraços
  4. Eu não sei onde estão os sources do quickreport no delphi3 :rolleyes: ..??? A versão Standard não é mesmo acompanhada dos fontes. Aparentemente seria mesmo este o modo. Eu a tenho procedo basicamente da mesma forma, mas talvez fosse interessante você testar o resultado das funções antes de chamar a seguinte. Assim, se estiver havendo algum erro com uma delas você fica sabendo onde. procedure TForm1.FormCreate(Sender: TObject); begin if CreateDir('C:\Temp') then begin if not SetGlobalEnvironment('TMP', 'C:\Temp') then ShowMessage('Houve erro ao tentar modificar a variável de ambiente "TMP".'); end else ShowMessage('Não foi possível criar o ficheiro temporário') end; Voce aida tem a opção de alterar esta variável na mão, como o colega Churc também sugeriu naquele post. Abraços
  5. Micheus

    Vias no Quickreport

    Bem estranho. :huh: como eu comentei no post, você tem que ajustar o nome do seu dataset. Voce deve estar usando um não?! Use-o no lugar de Table1. O exemplo, até posso passar, mas não terá muito mais do que os evento que já postei aqui (mas só na próxima madrugada). Abraços
  6. António44, eu já comentei no seu outro post, mas já que você abriu um novo tópico, vou repetir o texto aqui. Como você disse anteriormente que utiliza ainda o Delphi 3, é 99,999% de chance que seu problema seja este pelo qual eu já passei: Bug Com Quickreport 2 - D3 - veja a excelente explicação do colega Churc.
  7. António44, pode ter relação com aquele comentário que fiz sobre multiplicar o resultado da função por 1 (na expression). Perfeito! Não lembrei dele. :blush: Estive aqui a fazer uns testes e reparei que no meu Micro funciona tudo lindamente sem erro tenho 1.6GHz e 500 MB Ram mas o CPU vai até aos 97% e fica ali até que fecho o Preview do Report e no outro Micro onde dá erro tem 3.2Ghz e 256 MB Ram acontesse que roda o XP e eu estive a ver na memória disponivel ele tem apenas de 233696 sobra 50896 ou seja 50 MB Ram livres...será isto que faz com que ao criar o Report gera erros e bloqueia o programa...? o Report Preview é carregado na memória quando é chamado..? tenhgo duvida aqui se você Micheus me souber dizer qualquer coisa sobre isto eu agradeço.Como você disse anteriormente que utiliza ainda o Delphi 3, é 99,999% de chance que seu problema seja este pelo qual eu já passei: Bug Com Quickreport 2 - D3 - veja a excelente explicação do colega Churc. a questão dos espaços em branco, não é problema. Sempre que preciso usar uma bando para fazer algum tipo de operação em seus eventos, mas não mostro nada nelas, eu simplesmente altero a propriedade height para zero na inicialização do reletório. Quanto a retirada da banda rbDetail, eu nunca havia feito um relatório sem ela, então, não sei lhe dizer se isto tem algum efeito colateral.Já a parte da "contagem", não entendi a que se refere - não achei referência ao problema nos posts acima. :huh: Abraços
  8. Micheus

    agenda

    andre_seco, o que o seu professor lhe passou foi outro modo de gerar o resultado que você precisa - usando uma Stored Procedure. Neste caso, você passará a data equivalente ao primeiro dia da semana (segunda-feira) e o código da sala e terá todos os resultados para a semana (uma matriz). Da forma, como eu havia lhe sugerido, você teria passar a data do dia da semana sendo processado e o código da sala e teria apenas o resultado daquele dia (um vetor) - mas também poderíamos usar de unions e uma data de início, de modo similar, para gerar a matriz. (há muitas formas de se fazer uma mesma coisa) Quando você executar a sua consulta (ExecSQL), você ainda terá que fazer do modo como eu lhe sugeri no post#6 - terá que fazer um loop para ler cada registros do resultado que, do mesmo modo como eu havia sugerido, será composto por uma linha para cada dia da semana (segunda, terça,..., sábado). Assim, o que eu havia citado naquele post continua valendo. Observe que você praticamente faz o que postei lá, exceto que você preferiu acessar o campo do resultado através do seu índice Fields[<posição>] - que até é interessante. Mas, particularmente, não sou muito favorável a esta abordagem, pelo simples fato de que se você muda a posição de um campo na sua consulta, e não muda o índice no código, você passará a acessar a informação errada - cada caso é um caso, e este possível problema deve ser lembrado. Estou um pouco intrigado sobre como está sendo retornado o resultado da procedure, uma vez que não consta da declaração as colunas de saída (Stored Procedure - Parâmetros de Saída em SQL Server 2000). Na paleta ADO, há um componente específico para uso de stored procedures: ADOStoredProc, que talvez pudesse ser usado por você. Entretanto, se estiver conseguindo os resultados corretos com o ADOQuery, manda brasa. :D A questão de "colocar o If para todos os Edits" é realmente algo a ser contornado, e estava previsto naquela parte final em que citei: "Estando compreendido o processo, podemos melhorar e muito o código - você não vai querer repetir este código para as outras 5 colunas. Vai?!" Para adiantar, digo que a idéia é que você precisa ter o nome dos edits padronizados, como eu também já havia sugerido lá. Isto garantido, você faria uma laço para preenchimento dos edits (coluna) onde buscaria o nome do componente na lista. Segue um esqueleto: procedure TFPrincipal.BConsultaClick(Sender: TObject); var Linha, Coluna :Integer; Edit :TEdit; begin : : AdoQueryConsulta.ExecSQL; Coluna := 1; // referente Edits while not AdoQueryConsulta.EOF do begin for Linha := 1 to 13 do // referente Edits begin Edit := TEdit(FindComponent(Format('edAgenda$d%d', [Linha, Coluna]))); if Assigned(Edit) then // apenas garantindo que o comp. existe begin // aqui vão os if's... if AdoQueryConsulta.Fields[4].Value or AdoQueryConsulta.Fields[5].Value or : AdoQueryConsulta.Fields[16].Value then Edit.Text := AdoQueryConsulta.Fields[17].Text else Edit.Text := ''; end; end AdoQueryConsulta.Next; // próxima linha => próximo dia end; end; a função format irá preparar o nome do Edit a ser usado para preenchimento. Com este recurso, você já estará poupando muita digitação/código. Caso os campos do tipo bit, "gerem" no dataset AdoQueryConsulta campos do tipo TBooleanField, não há porque você testar .Value=True nos if's - a expressão avaliada já será booleana, logo não tem porque fazer a comparação. quando você executa stored procedures, não se usa o método Open ou a propriedade Active=True - usa-se apenas o método ExecSQL. Assim, no seu código, você pode suprimir algumas linhas e deixar apenas: // AdoQueryConsulta.Close; <*** Desnecessária se você usar AdoQueryConsulta apenas para esta consulta AdoQueryConsulta.SQL.Clear; AdoQueryConsulta.SQL.Add('exec dbo.ConsultaHorario ' + QuotedStr('25/12/2008') + ',1'); // AdoQueryConsulta.Active := true; < *** Sem função AdoQueryConsulta.ExecSQL; Veja se consegue adaptar ao seu código. Abraços
  9. Micheus

    Vias no Quickreport

    Eder, você esqueceu de por o Begin...End na opção else (o último Add está sempre sendo executado) - apenas isto). Eder, implementei o código que lhe sugeri e realmente, ainda faltou alguma coisa. Inclusive, constatei que havia escrito erroneamente o proprieda Font do QRLabel (coloquei, Fonts) - que bom que você corrigiu. Só para não deixar nada de fora, vou por o código básico para este método, ajuste nome de datasets e variáveis de acordo com seu código: // evento BeforePrint do QuickRep procedure TForm1.QuickRep1BeforePrint(Sender: TQuickRep; var PrintReport: Boolean); begin FNrVia := 1; // inicializa nº da via Table1.First; // posicionar no primeiro registro do dataset end; // evento AfterPrit da banda detalhe procedure TForm1.QRBand1AfterPrint(Sender: TQRCustomBand; BandPrinted: Boolean); begin Table1.Next; // avançamos para próximo registro end; // evento OnNeedData procedure TForm1.QuickRep1NeedData(Sender: TObject; var MoreData: Boolean); begin MoreData := not Table1.EOF; // imprimirá enquanto não for fim do dataset if not MoreData and (FNrCopias = 2) then // se não houver mais registros, mas NrCopias for 2 begin Inc(FNrVia); // incrementamos a via impressa MoreData := FNrVia <= 2; // Continuaremos a impressão enquanto houver via a ser impressa if MoreData then // se há via a ser impressa begin Table1.First; // posicionamos no início do dataset QuickRep1.NewPage; // forçamos uma nova página end; end; end;Obs: Não use a banda do tipo rbTitle, pois neste caso, ela será impressa apenas na primeira via - use um rbPageHeader - se necessário. Acho que agora, ficará completo. Abraços Motivo da edição: corrigido nome das variáveis (faltava o F inicial)
  10. Micheus

    Vias no Quickreport

    Eder, no botão que você manda imprimir ficaria como segue - supondo a criação do form do relatório em run-time: procedure TForm1.BtnImprimeClick(Sender :TObject); begin FrmImprimeNota := TFrmImprimeNota.Create(Self); try FrmImprimeNota.PrintPreview(StrToInt(Edit1.Text)); except FrmImprimeNota.Free; end; end; Abraços
  11. Gabriel Cabral, o "problema" está sendo gerado pela alteração do estilo do form que você está fazendo. Na verdade, quando a mensagem aparece, o form não está sendo minimizado, ele simplesmente perde o foco e o form principal da aplicação torna-se ativo. Voce tem duas opções: criar o form principal alterando seu estilo e parent (assim, os outros forms também assumirão este estilo) ou usar MessageBox para mostrar as mensagens e passa o handle da janela atual como parâmetro. ex.:MessageBox(Handle, 'Teste', 'Informação', MB_ICONINFORMATION or MB_OK); ShowMessage e MessageDlg, ambos fazem uso do mesmo código base, logo vão fazer a janela perder o foco. Abraços
  12. Micheus

    agenda

    andre_seco, você tem que me dar uma forcinha...DateTimePicker1 é, a título de exemplo, um componente TDateTimePicker da paleta Win32 e que é utilizado para obter datas. Na sua tela (imagem), você usa alguma outra coisa parecida com um combo - é deste "cara" que tem que vir a data. Ou, então, substitua-o pelo componente que usei no exemplo. Abraços
  13. Micheus

    Vias no Quickreport

    Eder, vou exemplificar utilizando o modo que costumo montar meus relatórios. Eu não costumo referenciar os componentes de outros forms dentro do meu form do relatório - uso sempre um procedimento, o qual chamo PrintPreview, e através dele passo os parâmetros que desejo (quando necessário) - penso que fica mais organizado/padronizado. Então, digamos que no seu relatório tenha o nome FrmImprimeNota: type TFrmImprimeNota = class(TForm) : private FNrVia, FNrCopias :Integer; public procedure PrintPreview(ANrCopias :Integer); end; : : // o BeforePrint da primeira banda onde esteja os componentes a serem alterados procedure TFrmImprimeNota.QRBand1BeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean); begin case FNrCopias of 1 : begin QRLabel1.Font.Style := [fsUnderline]; QRLabel4.Caption := 'Primeira via'; end; 2 : begin case FNrVia of 1 : begin QRLabel1.Font.Style := [fsUnderline]; QRLabel2.Font.Style := []; QRLabel4.Caption := 'Primeira via'; end; 2 : begin QRLabel1.Font.Style := []; QRLabel2.Font.Style := [fsUnderline]; QRLabel4.Caption := 'Segunda via'; end; end; end; end; end; Se for usar o método OnNeedData, a codificação abaixo deve funcionar: procedure TFrmImprimeNota.PrintPreview(ANrCopias :Integer); begin FNrCopias := ANrCopias; : : Quickrep1.PrinterSettings.Copies := FNrCopias; Quickrep1.Preview; end; procedure TFrmImprimeNota.QuickRep1BeforePrint(Sender: TQuickRep; var PrintReport: Boolean); begin FNrVia := 1; end; Se for usar o QRCompositeReport no form do relatório, a codificação muda um pouquinho, porque o mesmo relatório sendo inserido duas vezes, faria com que o NrVia fosse sempre 1: procedure TFrmImprimeNota.PrintPreview(ANrCopias :Integer); begin FNrCopias := ANrCopias; : : NrVia := 1; QRCompositeReport1.PrinterSettings.Copies := FNrCopias; QRCompositeReport1.Preview; end; procedure TForm1.QRCompositeReport1AddReports(Sender: TObject); begin QRCompositeReport1.Reports.Add(QuickRep1); QRCompositeReport1.Reports.Add(QuickRep1); end; procedure TForm1.QRCompositeReport1Finished(Sender: TObject); begin Inc(NrVia); end; Acho que deve funcionar corretamente - por gentileza, teste. Abraços p.s. você podia ter facilitado as coisas se tivesse informado qual dos métodos iria utilizar. ;)
  14. António44, faltou você dar uma olhada com "carinho" nas propriedades do seu TQRExpr. Olhe na janela Object Inspector as propriedades e você verá que existe uma chamada ResetAfterPrint - sugestivo não?! ;) Marque ela com True. Abraços
  15. estranha a informação... :huh: Format("%" [index ":"] ["-"] [width] ["." prec] type) onde o tipo (type) f corresponde a um número com ponto flutuante, conforme help: f = Fixed. The argument must be a floating-point value. The value is converted to a string of the form "-ddd.ddd...". The resulting string starts with a minus sign if the number is negative E a função tem por objetivo retornar uma string correspondente ao número passado como parâmetro. Em teoria, você deve ter definido estes campos, na sua tabela, como sendo do tipo CURRENCY. Sendo assim, este campo é numérico e o R$ não será gravado com ele. Mostrar o R$ é apenas uma questão visual, onde você deverá formatar o valor de modo a usar a informação de moeda.Infelizmente, a função CurrToStr não inclui a string da moeda no resultado, sequer o separador de milhar - então, tem que ser na mão mesmo. Para o processo inverso, é como o colega paulobergo, já lhe sugeriu: retire a informação de moeda e então o texto restante poderá ser convertido para número e gravado no banco. Abraços
  16. dan_visualdm, voce pode usar a instrução DELETE do SQL para faze isto. Noo caso do Access, ficaria algo como: delete * from tbl_hospedados where campo = 'D' entretanto, como você disse, há necessidade de excluir os registros filhos antes do pai, do contrário a integridade referencial fica furada! Voce poderia faze um combinação de instrução SELECT com DELETE. Constrói uma consulta SELECT com a tabela "pai" para obter os dados a excluir. Depois, usa o campo de referência desta consulta para passar como parâmetro para o dataset com o DELETE, que eliminará os "filhos". Excluidos os filhos, você pode excluir o pai. Voce não informou, então, vamos supor que o campo de referência em ambas chama-se Codigo. nas consulta do pai: select Codigo from tbl_hospedados where campo = 'D' isto retornará todos os códigos dos registros que deverão ser excluídos. delete * from tbl_filha where Codigo = :Codigo esta instrução SQL irá apagar todos os registros dos filhos de código passado como parâmetro. ... ADOQueryPai.Open; while not ADOQueryPai.EOF do begin ADOQueryFilho.Parameters.ParamByName('Codigo').Value := ADOQueryPai.FieldByName('Codigo').AsInteger; ADOQueryFilho.ExecSQL; ADOQueryPai.DeleteRecords(arCurrent); // ou a seguinte // ADOQueryPai.Delete; end; ADOQueryPai.Close; ...não usamos o ADOQueryPai.Next dentro do while, porque ao excluir o registro atual, automaticamente estaremos processando o próximo. A idéia seria mais ou menos esta, qualquer dúvida avise. E não esqueça de fazer um backup da base antes dos testes. ;) Abraços
  17. Micheus

    Herança

    Ednilson, nos próximos posts, onde existir código, faça a gentileza de utilizar a tag CODE para que a identação do código seja mantida e sua leitura facilitada. É desanimador ler códigos longos sem identação - não consegue-se visualizar facilmente as estruturas lógicas. Segundo o que consta no seu tópico no forum DevMedia, sua estrutura de herança é: TfrmPai +--> TfrmMestreConsulta | +--> TfrmConsFuncionarios | +--> : | +--> : +--> TfrmMestreCadastro +--> TfrmCadFuncionarios | +--> : +--> : e você diz que as variáveis referentes aos datasets estão declaradas na sessão public da classe TfrmPai: Tanto no código que você postou no DevMedia, quanto no que postou aqui, percebo que você inicializa o tabCadastro, no evento OnCreate do form TfrmCadFuncionarios, a partir da atribuição do endereço do dataset que existe no datamodule dmCadFuncionarios, também criado neste evento. Isto deve estar funcionando bem para o caso de quando você utilizar o botão de inclusão (btnNovo) - ao menos em uma primeira execução - porque neste momento, você chama o método NovoRegistro da classe TfrmPai o qual criará o form frmCadFuncionarios, que na seqüência será mostrado (ShowModal) e, ao ser fechado o form, este será eliminado através da chamada FreeAndNil. Entretanto, quando você utiliza o botão btnEditar, o seu método Editar, simplesmente utiliza a variável tabCadastro - que estará apontando para onde??? (Sabe-se lá. Esse o motivo do erro logo na primeira linha em que você a referencia) Acho que duas observações seriam pertinentes: 1) o dmCafFuncionarios, assim como o frmCadFuncionarios, deveria estar sendo liberado da memória - o que não consta do código (talvez, no OnDestroy ou OnClose do frmCadFuncionarios você esteja fazendo isto, mas não citou) 2) ao usar a opção de edição, pela lógica, você deveria novamente criar o frmCadFuncionarios, o que criaria o dmCadFuncionarios e inicializaria as variáveis dos datasets, e então, antes de chamar o ShowModal, posicionaria o dataset no registro desejado. Abraços
  18. António44, desculpe minha falha.Na cláusula ORDER BY, no caso do Paradox, não dá para usar a função. Em outros bancos, é possível até usar até o alias da coluna no SELECT (como Ano e Mes), mas com ele não dá e, então, temos que usar o nº referente à posição da coluna no SELECT que, em nosso caso, será 1 (Ano) e 2 (Mes): Select extract(year from data) as Ano, extract(month from data) as Mes, T.* from Tabela T where data between :DataIni and :DataFim Order by 1, 2, NomeClube, NomeEscalão Abraços
  19. António44, você há de convir que esta nova dúvida não tem relação com o relatório. Assim, visando manter a ordem aqui do forum e facilitando o aproveitamento da dúvida por outros colegas é sempre bom que um novo tópico seja aberto, nestes casos. ;) Mas vamos lá... fiquei meio confuso quanto a dúvida. :huh: Voce está querendo dizer que teria um botao (btEditar) para pôr o dataset, ligado ao DBGrid, em modo edição e então e, a partir daí, ao usar o botão Next do DBNavigator seguir para o próximo campo mas já com este no modo edição? Seria isto? Supondo que a resposta a meu questionamento anterior seja sim, podemos dizer que seria possível implementar esta facilidade, mas não funcionaria como você pensa. Não tem como editar uma linha do DBGrid e ir para outra sem que a informação alterada seja antes gravada - é automático. Não sei se você já observou, mas se no DataSource ligado ao DBGrid a propriedade AutoEdit=True (que é o padrão), ao tentar digitar qualquer coisa em uma coluna, automaticamente aquela linha entra em modo edição. Em todos os casos, se você estiver utilizando o Delphi 7 (D3 não tem o evento e os outros eu não conheço) e o dataset que você utiliza tem o evento AfterScroll, voce pode colocar o código abaixo para que cada vez que você mova de uma linha para outra, automaticamente ela entre em modo de edição: procedure TForm1.Table1AfterScroll(DataSet: TDataSet); begin if Dataset.State = dsBrowse then DataSet.Edit; end;neste caso, o seu botão edEditar ficaria sem função. Abraços
  20. Micheus

    Herança

    Ednilson, sem ver como você está fazendo isto, fica difícil, porque com certeza algo está errado. Voce vai precisar postar parte do código onde faz este procedimento bem como o header do form onde estão as declarações. (acho que deve ser o suficiente para uma avaliação do problema) Abraços
  21. Micheus

    Vias no Quickreport

    Eder, acho que você resolve isto fácil, utilizando: - QRComposite, veja Modelinho De Relatório, QuickReport - ou usando OnNeedData, veja Relatório Duplicado, Quick Report A questão de mudar o estilo do fonte para sublinhado ou não, você controla através de variáveis internas, conforme a situação atual em relação ao solicitado. Abraços
  22. Permitam-me um pitaco aqui... Colegas, baseado nestas informações, para fazer o agrupamento mensal, corretamente, ainda seria necessário colocar a "data" na cláusula ORDER BY, porque a banda de agrupamento avalia a expressão na sequência em que os dados são lidos do dataset. Entretanto, se nesta data aparecer ao dia, ainda assim o agrupamento não ficará correto pelos outros campos - exemplificando: // resultado de consulta ordenada por Data, NomeClube, NomeEscalão 01/12/2008 | Maritimo | Juvenis | 22 01/12/2008 | Olhanense | Infantis | 25 01/12/2008 | Olhanense | Iniciados | 22 01/12/2008 | Olhanense | Juvenis | 22 03/12/2008 | Fuseta | Infantis | 24 03/12/2008 | Olhanense | Seniores | 24 05/12/2008 | Fuseta | Infantis | 20 05/12/2008 | Maritimo | Infantis | 20 08/12/2008 | Olhanense | Infantis | 25 // resultado esperado para agrupamento correto no relatório é obtido // se a consulta for ordenada apenas usando o mês e ano da data, ou seja // ordenada por Ano, Mes, NomeClube, NomeEscalão 03/12/2008 | Fuseta | Infantis | 24 05/12/2008 | Fuseta | Infantis | 20 05/12/2008 | Maritimo | Infantis | 20 01/12/2008 | Maritimo | Juvenis | 22 01/12/2008 | Olhanense | Infantis | 25 08/12/2008 | Olhanense | Infantis | 25 01/12/2008 | Olhanense | Iniciados | 22 01/12/2008 | Olhanense | Juvenis | 22 03/12/2008 | Olhanense | Seniores | 24 o que permitiria facilmente o agrupamento por ano, mês, ou simplesmente mês/ano, neste formato: Dezembro/2008 + Fuseta | Infantis | 44 | Contador | Média + Maritimo | Infantis | 20 | Contador | Média | Juvenis | 22 | Contador | Média + Olhanense | Infantis | 50 | Contador | Média | Iniciados | 22 | Contador | Média | Juvenis | 22 | Contador | Média | Seniores | 24 | Contador | Média A consulta SQL ficaria deste modo: Select extract(year from data) as Ano, extract(month from data) as Mes, T.* from Tabela T where data between :DataIni and :DataFim Order by extract(Year from data), extract(Month from data), NomeClube, NomeEscalão No QuickReport a propriedade Dataset deve estar linkada ao dataset utilizado para a realização da consulta e as bandas ficam deste modo: - TQRGroup (1º) com a propriedade Expression contendo o campo Mes (no caso do agrupamento Mês/Ano) ---> contém TQRDBText com a propriedade DataField=Data e propriedade Mask=mmm/yyyy - TQRGroup (2º) com a propriedade Expression contendo o campo NomeClube ---> contém TQRDBText com a propriedade DataField=NomeClube - TQRGroup (3º) com a propriedade Expression contendo o campo NomeEscalão ---> Nada a mostrar - TQRBand com BandType=rbDetail ---> Nada a mostrar - TQRBand com BandType=rbGroupFooter (esta banda deve ser selecionada na propriedade FooterBand da banda group anteirior - NomeEscalão -> 3º) ---> TQRDBText com a propriedade DataField=NomeEscalão; ---> TQRExpr com a propriedade Expression contendo SUN(Total Atletas)*1.0; (Total Atletas é o campo do dataset, e o motivo de usar o "*1.0" você vê neste post) ---> TQRExpr com a propriedade Expression contendo COUNT; ---> TQRLabel para mostrar a média (resultado do SUM/COUNT) ---> No evento BeforePrint fazer o cálculo e atribuir ao TQRLabel. Os valores podem ser obtidos através a linha: QRLabel1.Caption := FormatFloat('0.00', QRExpr1.Value.dblResult/QRExpr2.Value.dblResult) onde: QRLabel1 é o label para mostrar o resultado da média; QRExpr1 contém o somatório de atletas QRExpr2 contém a quantidade de "jogos marcados" estes nomes dos componentes podem variar no seu relatório. Para cada um dos outros Group, você pode ter outras GroupFooter e obter os valores para aqueles agrupamentos, baseando-se nesta footer que configurei. No caso de uma totalização anual, poderia ser incluida no início mais uma banda Group com a propriedade Expression=Ano. Outra opção seria simplesmente utilizar uma banda Summary, mas esta representaria a totalização dos dados obtidos e caso nestes estejam informações de anos diferentes, os valores não corresponderiam ao esperado (valores anuais). Acredito que esteja em condição de funcionar a contento. Abraços
  23. Micheus

    agenda

    Então, a resposta é: "os Edits são para mostrar o nome do professor que reservou a sala naquele horário". e imagino que se este mesmo professor reservar outro horário no mesmo dia, então outro campo terá o valor 1 (e não o null). Certo?! ou seja, se a data escolhida cair em uma quinta-feira, você terá que mostrar os dados daquela semana de segunda a sexta-feira em que o dia se encontra. Isso não é problema.Com a data em mãos, você obtém o dia da semana a que corresponde e calcula a data referente a segunda e sexta feira. A função DayOfWeek (unit SysUtils), retorna o número do dia (Domingo = 1 ... Sábado = 7) Não entendeu não.O seu exemplo anterior tem o resultado mais de acordo com o que tentei explicar. Com a estrutura de tabela que você tem, você terá que trazer todos os campos necessários, logo a consulta continuaria sendo aquela que propus, adicionado do campo professor: select M1, M2, M3, M4, M5, T1, T2, T4, N1, N2, N3, N4, Professor from Reserva where CodSala = :CodSala and Data = :Data que poderá resultar em algo como abaixo (baseado em seu exemplo): |null|null|null|null|null|_1|null|null|null|null|null|null|null|Augusto| |null|null|null|_1|null|null|null|null|null|null|null|null|null|Coelho| |null|null|null|null|null|null|null|null|null|_1|_1|null|null|Carlão| É como deverá ser seu resultado se houverem reservas para 3 professores neste dia. Possivelmente. Mas você tem que passar como parâmetro o valor dos componentes e não uma string com seu nome, ou seja, no lugar de 'DateTimePicker1' será DateTimePicker1.Date e no lugar de 'DBCDsala', ... bom, esse eu não sei. Que componente é este? Um ComboBox, um DBComboBox, um DBLookupComboBox? Mas você nota que você não quer apenas esta informação? (o professor) Terá que usar a consulta como pus acima. Com a consulta correta, você terá o resultado em condições de ser usado para mostrá-lo na tela. Então, baseado no exemplo acima (3 linhas de resultado), digamos que o resultado tenha sido obtido para o dia 08/12/2008 (segunda-feira): |null|null|null|null|null|_1|null|null|null|null|null|null|null|Augusto| |null|null|null|_1|null|null|null|null|null|null|null|null|null|Coelho| |null|null|null|null|null|null|null|null|null|_1|_1|null|null|Carlão| você precisa "varrer" cada linha e verificar cada campo de Mn até Nn e onde o valor do campo não for nulo, você coloca o nome do professor no Edit correspondente. Para ser sincero, se você usar um StringGrid, sua vida pode ficar mais fácil - vai trabalhar com Linha (horários) x Coluna (dia da semana). Mas, por hora, vamos sofrer um pouquinho, assim você aprende mais. :D Supondo que você tenha usado uma nomenclatura formatada/padronizada para o nome de seus edits, digamos que os edits da primeira coluna (ref. a segunda-feira), tenham o nome: edAgenda11, edAgenda12, edAgenda13 ... edAgenda113 (ou seja, edAgenda<coluna><linha>); Ao ler cada linha do dataset (sua consulta), o edit correspondente ao horário é inicializado com o nome do professor: // procedimento para inicialização da agenda na tela - Implementada apenas para a segunda-feira procedure TForm1.InicializaAgenda; var CodSala :Integer; Data :TDateTime; begin CodSala := // atribui o valor em DBCDsala (não sei que componente é) // mas a título de teste, você pode mover um valor fixo para esta variável Data := DateTimePicker1.Date; // use uma segunda-feira para o teste ADOQuery1.SQL.Clear; // limpa a propriedade SQL ADOQuery1.SQL.Add('select M1, M2, M3, M4, M5, T1, T2, T4, N1, N2, N3, N4, Professor'); ADOQuery1.SQL.Add('from Reserva'); ADOQuery1.SQL.Add('where CodSala = :CodSala and data = :Data'); ADOQuery1.Parameters.ParamByName('CodSala').Value := CodSala; ADOQuery1.Parameters.ParamByName('Data').Value := Data; ADOQuery1.Open; // executa a consulta while not ADOQuery1.EOF do // continua no while enquanto não for fim do dataset begin if not ADOQuery1.FieldByName('M1').IsNull then // se não for nulo, atribui nome do professor edAgenda11.Text := ADOQuery1.FieldByName('Professor').AsString else // do contrário, limpa o conteúdo edAgenda11.Text := ''; if not ADOQuery1.FieldByName('M2').IsNull then edAgenda12.Text := ADOQuery1.FieldByName('Professor').AsString else edAgenda12.Text := ''; if not ADOQuery1.FieldByName('M3').IsNull then edAgenda13.Text := ADOQuery1.FieldByName('Professor').AsString else edAgenda13.Text := ''; : : neste intervalo vão as outras atribuições : if not ADOQuery1.FieldByName('N4').IsNull then edAgenda113.Text := ADOQuery1.FieldByName('Professor').AsString else edAgenda113.Text := ''; ADOQuery1.Next; // avança para o próximo registro no dataset end; ADOQuery1.Close; end;Observe que este procedimento está programado para processar apenas um dia, e conforme citei, este dia seria uma segunda-feira. Pelo seu pouco conhecimento, sugiro que você tente compreender e implementar o falei até aqui, bem como faça o teste apenas para esta data (uma segunda-feira). Depois teremos que calcular a data de início e término da semana para que possamos preencher toda a agenda. Estando compreendido o processo, podemos melhorar e muito o código - você não vai querer repetir este código para as outras 5 colunas. Vai?! ;) Abraços p.s. Como meu post ficou enooorrrme, não QUOTE todo ele, se for respondê-lo - vai tornar péssima a leitura do seu.
  24. pimpocvl, aparentemente isto seria o correto. Observe o seguinte, pelo nome da tabela e do campo NUMEROATENDIMENTO, imagino que em toda ela, exista a ocorrência de um determinado número uma única vez. Assim, caso você filtre este campo, passando um valor válido, mas filtre outros campos de modo que o valor não corresponda aos valores encontrados nesta única linha válida, então seu resultado será mesmo nulo. Deixo no link a seguir exemplo que faz uso do método que lhe indiquei: Teste Filtro.zip (Descompacte-o um uma pasta específica. Já tem um executável dentro dele - apenas renomeie mudando a extensão de .ex_ para .exe) Nele utilizei dois componentes, um da paleta Interbase e outro da ZeosLib. Criei uma tabela com estrutura parecida com a sua e poucos dados - apenas para avaliação. Experimente inicialmente filtrar o campo STATUS. Observe o resultado. Depois, utilize outros campos, passando um dos valores obtidos neste resultado e observe que o filtro vai se ajustando. É isso. Desculpe a demora em respondê-lo, mas estive ausente nos últimos 10 dias e queria montar um exemplo com o código que lhe exemplifiquei. Abraços p.s. a propósito, naquele código, na parte dentro do teste do Param2 <> '' o if deveria estar testando se Filtro não era nulo e não Param1: ... if Param2 <> '' then begin if Filtro <> '' then // ****** AQUI Filtro := Filtro +'AND ' else Filtro := ' WHERE '; Filtro := Filtro +'CODIGOCLIENTE = :pParametro2 '; end;
  25. dan_visualdm, você deverá fazer mais ou menos o que tem neste post - tem que ajustar o sinal utilizado (está o ">") e nome do campo. Existem muitos tópicos relacionados a este tipo de assunto, usando a busca pelo texto do evento OnDraw, veja os resultados. Caso você ainda precise tirar dúvidas sobre este assunto, por gentileza, crie um tópico específico para não desvirtuarmos este assunto. ;) Abraços
×
×
  • Criar Novo...