
Micheus
Veteranos-
Total de itens
3.189 -
Registro em
-
Última visita
Tudo que Micheus postou
-
Como Compilo Um Programa Com Banco Paradox Para Rodar Em Qualquer Máqu
pergunta respondeu ao Tiagomanutenção de Micheus em Delphi, Kylix
Tiagomanutenção, você não mensionou, então estou supondo que você utilizou como banco de dados o Paradox. Se bem me lembro, você deverá instalar o BDE em todas as máquinas que instalar o programa. Como você utiliza o alias definido via BDE, você terá que criá-lo nestas máquinas e apontar para o diretório aonde está sua base de dados (nomalmente uma pasta no servidor, a qual você pode mapear como disco de rede nos PC's) Acho que se você gerar uma instalação do programa, utilizando o InstallShield ele deve possibilitar a inclusão do DBE também. Abraços -
Louco Sam, dê uma lida em alguns artigos relacinados a modelagem de dados. Irá lhe ajudar muito. Um pouco de teoria se faz necessário - na prática, ajustes são feitos, mas o embasamento é teórico. Artigo na plugMasters, por Mauri Gonçalves (siga a sequência) 1) Modelagem de Dados 1 - Visão Geral 2) Modelagem de Dados 2 - As Entidades 3) Modelagem de Dados 3 - Os Relacionamentos 4) Modelagem de Dados 4 - Validação do modelo ER 5) Modelagem de Dados 5 - Abordagem Relacional 6) Modelagem de Dados 6 - Transformação entre Modelos Este também é interessante, apesar da citação do uso de uma ferramenta de modelagem de dados (ERWin), o conceito/ilustrações apresentados são bons: - Conceitos Básicos de modelagem de dados (macoratti.net) você vai observar que o usual é chegar até a 3ª forma normal (3FN; exitem 5) ao utilizar a metodologia de normalização do banco de dados. (Wikipedia - Normalização de Dados) Mais um relevante: Integridade Existencial e Referencial Abraços
-
Utilizando Comandos Select, Para Pesquisa.
pergunta respondeu ao schaukoski de Micheus em Delphi, Kylix
schaukoski, este tópico já está resolvido (pelo outro tópico)? Senão, pelo que eu já tinha entendido lá, você poderia fazer isto (eliminar linhas com código igual numa coluna ou em outra) com o SQL que coloquei neste post. Abraços -
Que erro seria esse? Qual a mensagem? Não teria relação com uma chave não inicilizada - campo nulo?
-
Locate, Como Posicionar O Ponteiro Na Tabela Com Locate
pergunta respondeu ao schaukoski de Micheus em Delphi, Kylix
schaukoski, você não poderia utilizar uma query para fazer esse trabalho? Colocaria na instrução SQL desta forma:DELETE relaciona WHERE CODFICHA = :COD_ELIMINAR OR CODRELACIONADO = :COD_ELIMINAR Depois de você obter a confirmação da exclusão, pelo usuário, você executaria esta query através do ExecSQL; antes porém, passando o parâmetro COD_ELIMINAR que seria o código que está dos dois lados da sua tabela. -
Xtreme testing framework for Borland Delphi programs (link)Wikipédia: "DUnit é uma ferramenta de código aberto para testes de unidade em programas desenvolvidos na linguagem Pascal, no Delphi, baseada na ferramenta JUnit voltada para a linguagem Java." (link) Artigos no DevMedia - Test-driven Development with Delphi - Testes Unitários O assunto parece interessante. Abraços
-
Locate, Como Posicionar O Ponteiro Na Tabela Com Locate
pergunta respondeu ao schaukoski de Micheus em Delphi, Kylix
schaukoski, Vamos deixar seu código mais legível: procedure TFormTCadCF.SBrelaccancelClick(Sender: TObject); var codficha,codrelacionado,codrelacao,codinverso:string; begin codficha:=SDSrelacionacodficha.asstring; codrelacionado:=SDSrelacionacodrelacionado.asstring; codrelacao:=SDSrelacionacodrelacao.asstring; if application.MessageBox('Deseja Excluir Relação?', 'Relacionamento', mb_yesno+mb_iconquestion)=idyes then begin SDSrelaciona.delete; // *** 1 if dm.SDSrelacao.Locate('codrelacao', codrelacao,[]) then codinverso:=dm.SDSrelacaoinverso.AsString; if (dm.SDSrelaciona.Locate('codficha', codrelacionado,[])) and // *** 2 (dm.SDSrelaciona.Locate('codrelacionado', codficha,[])) and // *** 3 (dm.SDSrelaciona.Locate('codrelacao', codinverso,[])) then dm.SDSrelaciona.Delete; // *** 4 end; end;Observe as marcas "// *** n": 1) em 1 você tenta excluir o item atual em SDSrelaciona; 2) em 2 e 3 parece que os parâmetros codficha e codrelacionado estão trocados, é assim mesmo? 3) o que você pretende excluir em 4, já que supostamente você já excluiu em 1? -
EU acho que teriamos um caminho complicado (e diversificado) para chegar até o nome da tabela. Vou sugerir o que eu costumo fazer (mas utilizando seus componentes) e você vê se lhe atende. Eu crio uma função no datamodule principal de minha aplicação, aonde normalmente tenho o database/transaction para conexão ao banco, e para ela passo o nome da tabela e campo a buscar o max. Neste datamodule adiciono um componente exclusivamente para ser utilizado por esta função - em nosso caso um TSQLDataSet (SQLDataSetMax) function TDMMain.GetNewFieldCod(TableName, FieldName :string) :LongInt; begin SQLDataSetMax.CommandType := ctQuery; SQLDataSetMax.CommandText := 'SELECT (MAX('+FieldName+')) AS '+FieldName+' FROM '+TableName; SQLDataSetMax.Open; Result := SQLDataSetMax.FieldByName(FieldName).AsInteger +1; SQLDataSetMax.Close; end; a chamada a função eu faço no BeforePost da tabela em questão, no seu caso, ClienteDataSet em questão, observando se ela está no modo inserção: procedure TDMCliente.CDSClienteBeforePost(DataSet: TDataSet); begin if CDSCliente.State = dsInsert then CDSClienteCOD_CLIENTE.AsInteger := GetNewFieldCod('CLIENTE', 'COD_CLIENTE'); // ou, caso você não adicione os fields ao componente ClienteDataSet: // CDSCliente.FieldByName('COD_CLIENTE').AsInteger := GetNewFieldCod('CLIENTE', 'COD_CLIENTE'); end; Bom, não tenho certeza 100% se funcionaria para a estrutura que você disse estar utilizando, mas acredito que funcione com alguns ajustes - se necessário. É no que posso lhe ajudar Abraços
-
Carlos Rocha, acho que entendi qual sua necessidade. Vou pensar em alguma coisa (exemplo) que possa lhe ajudar. Se algum outro colega, tiver algo pronto nestes moldes que possa ajudar o colega, por gentileza posta aí. Abraços
-
Que bom. prefiro esta opção por esses motivos:- não fico na obrigação de responder - já verifico meu e-mail poucas vezes por semana; - há outros colegas aqui que poderão lhe ajudar; - e outros colegas poderão aprender com suas dúvidas. Abraços
-
O que ocorre é que o componente ClienteDataSet não possui a propriedade TableName - que existia no IBTable. Observe aonde foi que você definiu, no seu ClientDataSet, a tabela a ser utilizada. Poderiaser na propriedade CommandText ou se há um DataSetPrivider definido para este componente, então na sua propriedade DataSet você poderá descobrir o nome da tabela.De qual forma você está utilizando o componente?
-
Jose, apena um comentário: você não poderá utilizar ExecSQL para retornar linas de um SELECT, neste caso tem que utilizar Open; Do help sobre ExecSQL:"To execute a query at runtime, use one of the following methods: - Open executes a query that returns a result set, such as SELECT. - ExecSQL executes a query that does not return a result set, such as INSERT, UPDATE, or DELETE. Note: If you do not know at design time whether a query will return a result set at run time, code both types of query execution statements in a try...except block. Put a call to the Open method in the try clause, and put the ExecSQL method in the except clause. To avoid executing a statement twice (for example, in the case of an empty result set), check for an exception of type ENoResultSet before executing the ExecSQL method in the except clause." você irá colocar, para cada linha retornada, os campos um após o outro? Posso perguntar porque colocá-lo em um DBMemo? Vou exemplificar esta forma que entendi, utilizando um TMemo e utilizando a dica do help. Caso você utilize um DBMemo para armazenar o resultado em uma tabela, o correto seria utilizar o nome do campo associado a ele, ao invés de utilizar a propriedade Lines. procedure TForm1.Button4Click(Sender: TObject); var Idx :Integer; Resultado :string; begin try SQLQuery1.Open; // executa comandos SELECT Memo1.Lines.Clear; while not SQLQuery1.EOF do begin for Idx := 0 to SQLQuery1.FieldCount -1 do Resultado := Resultado +', ' +SQLQuery1.Fields[Idx].AsString; Memo1.Lines.Add(Resultado); SQLQuery1.Next; end; SQLQuery1.Close; excep SQLQuery1.ExecSQL; // executa comandos UPDATE, DELETE, ... ... end; end; Abraços
-
fernando_vip, se você tem um DBImage na sua tela, pode utilizar desta forma // lê do arquivo em disco para o DBImage Table1.Edit; if OpenDialog1.Execute then DBImage1.Picture.LoadFromFile(OpenDialog1.filename); Table1.Post;você não precisa necessariamente dar o post aqui, bem como colocar a tabela em edição, já que ela já pode estar neste situação - é apenas um exemplo. O importente é lembrar que para alterar o conteúdo da sua imágem na tabela, você deverá tê-la posto em edição ou inserção e ao final das alterações, gravar (post). Tem ainda este post do Paulo Nobre aonde ele apresenta duas formas de ler e gravar as imagens no banco.
-
E nem seria necessário o uso das variáveis auxiliares. Concordo com você Pogr'amador, não sei de onde saiu este tipo de procedimento, mas vemos o tempo todo e imagino que possa dificultar muito a compreensão do conceito em si - atualizar a tabela - não os DBEdit's. Também dificulta muito no auxílio quando as mensagens de erros são interpretadas. O ideal é que sejam colocadas as mensagens originais e a parte do código aonde ela ocorre (quando possível) - como deve ser o caso deste erro.
-
na sua unit U_CADFILM, na procedure TFRRM_CADFILM.btnFotoClick, você está tentando acessar um componente que realmente não foi declarado. Veja a linha: DataSource1CAPA.LoadFromFile(OpnPctrDlg1.FileName); - este item não existe no seu form! você não respondeu as outras questões: 10 inserções em uma tabela específica ou o somatório das inserções em qualquer tabela? por este post, parece que você já resolveu o problema inicial. Tá até dando erro de execução... :huh: Abra um tópico para cada dúvida, e se resolvida informe, do contrário vira uma salada e você pode não ter algumas das dúvidas respondidas. Abraços
-
que erro? Qual DB? 10 inserções em uma tabela específica ou o somatório das inserções em qualquer tabela?
-
Yugi Moto, neste caso, a falha está no meu exemplo. Troque: CommandLine := Format('demo.exe @MY_ASS@ _server%s', [ini.readstring('site', 'patch', 'about:Erro')]); por CommandLine := Format('demo.exe @MY_ASS@ _server %s', [ini.readstring('site', 'patch', 'about:Erro')]); Ou seja, acrescente o espaço antes do %s (%s é o lugar onde a string lida será inserida). Caso, corrigido isto, ainda não haver a execução esperada, então o problema reside noutro ponto. Bom, agora você também já sabe utilizar melhor o break-point e evaluate/modify, isto lhe ajudará bastante no processo de "debugar" suas aplicações. Abraços
-
para isto, supondo a declaração do parâmetro na SQL da sua ZqryClientes (conforme propus no post anterior), você faz algo como: criar um procedimento para popular sua lista: procedure TFormCotacoes.PopulaComboBox; begin ComboBoxCli.Items.Clear; ZqryClientes.Close; // com o % vamos buscar todos os clientes ZqryClientes.ParamByName('Nome').Value := '%'; ZqryClientes.Open; while not ZqryClientes.EOF do begin ComboBoxCli.Items.Add(ZqryClientesNome.AsString); ZqryClientes.Next; end; end; Não esqueça de alterar a propriedade Sorted=True no seu ComboBoxCli. como o conteúdo que você digita é o desejado de ser procurado, no evento OnChange que ocorre quando você digita na caixa de texto do combobox ou seleciona um item dela, é que iremos posicionar o item da tabela cliente:procedure TFormCotacoes.ComboBoxCliChange(Sender: TObject); begin //Verifica se a tabela esta em estado de edição ou inserção if (ZTableCotacoes.State in [dsInsert,dsEdit]) then begin ZqryClientes.Close; // copiamos o texto na caixa da combobox so início até a posição do cursor // se você está digitando, será o sub-string digitado; se for uma seleção será todo o texto ZqryClientes.ParamByName('Nome').AsString := Copy(ComboBoxCli.Text, 1, ComboBoxCli.SelStart +'%'); ZqryClientes.Open; if not ZqryClientes.EOF then begin ZTableCotacoesCodigo_Cliente.Value:=ZqryClientesId.Value; ZTableCotacoesCodigo_Cliente.Value:=ZqryClientesId.Value; ZTableCotacoesLocal_Cobranca.Value:=ZqryClientesEndereco.Value; ZTableCotacoesCPF.Value:=ZqryClientesCpf.Value; ZTableCotacoesCNPJ.Value:=ZqryClientesCNPJ.Value; end else begin ZTableCotacoesCodigo_Cliente.AsString:=''; ZTableCotacoesLocal_Cobranca.AsString:=''; ZTableCotacoesCPF.AsString:=''; ZTableCotacoesCNPJ.AsString:=''; end; end; end; Acho que é o que você vai conseguir com a sugestão acima. Dê uma conferida. Importante: a sua combobox deve ser populada a cada inclusão ou edição, porque podem ocorrer inclusões na sua tabela Clientes por outro usuário. No momento em que você coloca a tabela em edição ou inserção, você deve chamar o procedimento que popula a lista (PopulaComboBox). No caso específico decolocar no modo edição, você tem que posicionar seu ComboBox no cliente correto. Então, teria que executar algo como: begin ... PopulaComboBox; ComboBoxCli.ItemIndex := ComboBoxCli.Items.IndexOf(NomeCliente_em_cotacoes); end; Me diga se captou a idéia. Observei que você mudou alguns campos. você não tem mais o campo nome na tabela de cotações? Porque se agora tem apenas o código, teremos que fazer alguns ajustes no exemplo que coloquei acima, já que precisará olhar o codigo. Abraços
-
com licença, uma curiosidade: você guarda algum tipo de informação referente ao desenho das linhas? Tipo tem algum tipo de estrutura que indique a sequência de linhas que desenha?
-
o break-point por si só não diz nada. Na figura, observe que o break que você marcou na declaração de CommandLine é inválido. Só podem haver válidos aonde você observar que tem aquelas "bolinhas azuis". beleza?! O que vai realmente lhe ajudar em alguma coisa, é aquele break na linha: WinExec(....). Quando você está executando o programa e ao clicar o botão Button1, ao parar a execução do programa nela, você pode avaliar o conteúdo da sua string CommandLine. Para isto você pode simplesmente posicionar o cursor sobre o nome da mesma (na linha anterior) e teclar CTRL+F7. Vai aparecer uma janela de avaliação (Evaluate/Modify) aonde você poderá observar como ficou o texto formatado. Daí você vai ter certeza de que está realmente havendo ou não um problema com a leitura do arquivo ini - se não houver sua linha de comando estará correta e o problema pode ser outro. Para continuar a execução, após a parada no break, você pode utilizar F8 (continha execução linha-a-linha, na verdade quase isso) ou F9 para executar o programa sem paradas (exceto se passar novamente por algum break).
-
desculpe-me, mas acho que falta a declaração do parâmetro neste SQL:Select * from clientes where Nome like :Nome order by Nome; e daí para filtrar apenas o segmento digitado e popular uma lista com tudo o que começa com o que foi digitado, você adicionaria o '%' ao final da string procurada quando utilizar o ParamByName. Exclareça-me: 1) que informações você pretende adicionar a ComboBox1? Seria uma lista de pessoas que comecem com o nome informado em CotacoesNomeCli? Se for vale o primeiro comentário que fiz. 2) você realmente tem e mantém as informações do cliente duplicadas nas duas tabelas Clientes e Cotações? 3) como você buscaria os dados corretos do cliente, desta forma, se por acaso puderem haver clientes homônimos? você sempre estará posicionando no primeiro que encontrar. lembre-se, se você está obtendo uma possível lista de clientes para popular sua ComboBox1, é de imaginar que se realmente foi digitado o nome parcial e você quer atualizar os demais campos para o primeiro cliente da lista, você terá que após chegar ao fim da lista no while..do, novamente mover o apontador do dataset para a primeira linha:... while not ZqryClientes.EOF do begin ComboBoxCli.Items.Add(VarToStr(ZqryClientesNome.Value)); ZqryClientes.Next; end; ZqryClientes.First; // *** <=== Posiciona no primeiro cliente compatível if not ZqryClientes.IsEmpty then ... será que isto não estaria associado ao primeito comentário? Abraços
-
perfeitamente. acredito que na maioria dos casos. De um modo geral você emite relatórios baseados em algum tipo de critério e, neste caso, é onde mais se aplica o uso de query já que você facilmente introduzirá filtros na sua consulta - dados num período, itens de um determinado cliente, ... Lembre-se sempre, que no QuickReport, você deverá ter no mínimo uma banda: rbDetal; Esta banda será processada para cada linha proveniente do dataset ligado ao Quickrep. O dataset utilizados em um QRDBText não precisam ser necessariamente o mesmo do QuickRep. O dataset "diz" apenas de onde será obtido o dado a ser impresso. Vejamos um exemplo (bem bobo), para mostrar o que quero dizer: digamos que temos as seguintes tabelas: +------------+ +------------+ +------------+ | CLIENTES | | CIDADE | | CEP | +------------+ +------------+ +------------+ |COD_CLIENTE | | COD_CIDADE | | COD_CEP | |NOM_CLIENTE | | NOM_CIDADE | | NOM_RUA | |COD_CEP | | DSC_UF | +------------+ |NUM_ENDERECO| +------------+ |COD_CIDADE | +------------+ Então ao criar um relatório que mostre os dados do clente, você poderia fazer a mesma coisa de, pelo menos, duas formas diferentes: 1) Utilizando um único dataset do tipo TQuery, você faria uma consulta em que retornaria todos os dados do cliente em uma única linha. O SQL ficaria assim:SELECT C.COD_CLIENTE, C.NOM_CLIENTE, P.NOM_RUA, C.NUM_ENDERECO, D.NOM_CIDADE, D.DSC_UF FROM CLIENTES C, CIDADE D, CEP P WHERE C.COD_CEP = P.COD_CEP AND C.COD_CIDADE = D.COD_CIDADE ORDER BY C.NOM_CLIENTE Com esta situação, este dataset seria utilizado tanto no Quickrep quanto nos componentes QRDBEdit's. Mas poderia ser feito também de outra forma: 2) Utilizando um dataset do tipo TTable, ligado ao QuickRep, você acessaria os dados da tabela cliente e colocaria este mesmo dataset apenas nos campos que não vem das tabelas relacionadas (Cidade e CEP); você, então, utilizaria componentes do tipo TQuery para buscar os demais campos, donde resuta que você teria dois componentes do tipo TQuery (um para Cidade e outro para CEP) com os seguintes SQL, respectivamente:*/ SQL para obter o nome da rua /* SELECT NOM_RUA FROM CEP WHERE COD_CEP = :COD_CEP */ SQL para obter o nome da cidade e uf /* SELECT NOM_CIDADE, DSC_UF FROM CIDADE WHERE COD_CIDADE = :COD_CIDADE Observe que cada SQL foi definido para receber um parâmetro (:nome_parametro). Não por acaso, utilizamos o mesmo nome dos campos que existem na tabela principal (nosso dataset TTable ligado ao QuickRep). Adicionando um DataSource em que atribuímos a sua propriedade DataSet o dataset principal (Cliente); Selecionamos na propriedade MasterSource dos componentes TQuery (Cidade e CEP) este DataSource. Disto resulta que, ao ser movimentado o ponteiro de registros (linha) na tabela principal (Cliente), as querys serão reexecutadas, obtendo os respectivos parâmetros (via datasource) da tabela principal. Para tanto, antes do preview, devem ser abertas as query's e após a tabela. Algo tipo:procedure TFormBtnImprimeClick(Sender :TObject); begin QryCEP.Open; QryCidade.Open; TabCliente.Open; try QuickRep.Preview finally TabCliente.Close; QryCEP.Close; QryCidade.Close; end; end; Há, ainda, outras formas de fazer este mesmo relatório. você pode questionar: mas porque usar o 2º exemplo, que utiliza muito mais componentes, ao invés de utilizar o 1º ? Eu diria: É bom que você saiba que existe esta possibilidade porque, possivelmente, haverá algum momento na sua vida de programador que esta será a melhor alternativa (senão a única) para construir determinado relatório (não tão simples quanto o do exemplo). Inclusive, uma situação comum, é quando você tem relatórios com sub-detalhes, onde na banda tipo QRSubDetail você tem a propriedade DataSet com outra origem de dados que não a do QuickRep, mas vinculada a ele (p.e. na banda detalhe fica o header de um pedido - Pedidos - e na sub-detalhe os itens - ItemPedidos) Abraços p.s. não tem jeito - escrevi um livro denovo :D
-
Se utilizar um gerenciador de alias, pode ficar ainda mais simples. Eu utilizo um versão para o Firebird (Firebird Control Center), onde instalado no servidor, você configura um alias (apelido) que apontará para a localização física do arquivo do banco de dados no disco do servidor. Daí, nas outra máquinas da rede (client's) é instalada apenas a dll (fbcvlient.dll ou gds32.dll) na pasta system (win95,98,Me) ou system32(>= win 2K). No programa, a string de conexão você utilizaa apenas o servidor:alias Nada de mapeamentos, nada de diretórios fixos ou gravados em configurações. Para o IB tem o ibAM - IB Alias Manager 1.3a (download em Ramos da Informática). Se alguém já trabalhou com ele, poderia explicar aqui como instalá-lo e configurá-lo para que interessados possam utilizá-lo? Abraços
-
Carlos Rocha, este código está funcionando como esperado? você não colocou o conteúdo de sua query, mas parece-me que você está procurando na tabela clientes, os dados do cliente cadastrado na tabela cotações: ZqryClientes.Close; ZqryClientes.ParamByName('Nome').Value:=ZTableCotacoesNomeCli.Value; ZqryClientes.Open; e desta forma, se você encontra terá possivelmente apenas um registro como resultado. Do contrário, não terá nenhum. Assim sendo, esta outra parte do código faria com que o combobox1 tivesse apenas um registro ou nenhum: ZqryClientes.Refresh; // *** não é necessário, você acabou de abrir a consulta ZqryClientes.First; //Verifica se encontrou while not ZqryClientes.EOF do begin ComboBoxCli.Items.Add(VarToStr(ZqryClientesNome.Value)); ZqryClientes.Next; end;aliás, se for encontrado um cliente este será adicionado ao ComboBox e a lista irá crescer a cada cliente encontrado, já que apenas ao encontrar você adiciona o cliente a lista do combo. Como você colocou este procedimento dentro do evento OnChange do ComboBox1, a cada vez que o texto no combobox for alterado (por digitação ou seleção da lista) ele executará exatamente a mesma coisa. Entendi errado? Dê uma conferida, porque não tenho certeza no momento, mas deve existir um método AsString no componente field da query da Zeos lib. Neste caso, você poderia substituir a linha: ComboBoxCli.Items.Add(VarToStr(ZqryClientesNome.Value)); por ComboBoxCli.Items.Add(ZqryClientesNome.AsString); para fazer isso, primeiramente você deverá ter incluído estes campos na sua query aonde você busca os dados de um determinado cliente (imagino que seja ZqryClientes). Com isto, após posicionar corretamente o cliente (imagino que você quizesse fazeri isso no procedimento acima), bastaria mover os campos para os edit's desejados. Abraços
-
Pela mensagem, na unit WSocket, ou em qualquer uma que ela utilize há a declaração de PSockAddr.Dando uma pequisada, este tipo deveria ser um ponteiro para uma extrutura deste tipo (ver Torry's): PSockAddr = ^TSockAddr; TSockAddr = packed record Family: Word; Port: Word; Addr: Longint; Zeros: array[0..7] of Byte; end; Se realmente não está declarada em alguma das units utilizadas pela que está acusando o erro, talvez seja o caso de você declará-la lá. Abraços