Editorial - The Club - O maior clube de programadores do ... · e ergonomia, ou seja, não atendem...

32

Transcript of Editorial - The Club - O maior clube de programadores do ... · e ergonomia, ou seja, não atendem...

editorial

03

sumário

THE CLUBAv. Profº Celso Ferreira da Silva, 190

Jd. Europa - Avaré - SP - CEP 18.707-150Informações: (14) 3732-3689

Suporte: (14) 3733-1588 - Fax: (14) 3732-0987

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected] Informações: [email protected]

DúvidasCorrespondência ou fax com dúvidas devem

ser enviados ao - THE CLUB, indicando “Suporte”.

OpiniãoSe você quer dar a sua opinião sobre o clube

em geral, mande a sua correspondência para a seção “Tire sua dúvida”.

ReproduçãoA utilização, reprodução, apropriação,

armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada

publicação da revista “The Club Megazine” são terminantemente proibidos sem autorização

escrita dos titulares dos direitos autorais.

Impressão e acabamento:HIPERGRAF Indústria Gráfica

Tel.: (14) 3641-1665 - Cep 17340-000Rua Francisca A. Pereira Borges, 436

Barra Bonita - Vila São CaetanoTiragem: 5.000 exemplares

Copyright The Club Megazine 2007

Diretor TécnicoMauro Sant’Anna

Colaboradores Mauto Sant´Anna

Delphi é marca registrada da Borland International, as demais marcas citadas são registradas

pelos seus respectivos proprietários.

- Editorial .................................................................................................... 03

- Novidades na linguagem - Parte 4 ............................................................ 04

- Testes Comportamentais: Psicológico ou Tecnológico ............................. 06

- SQL Server Management Studio Express (SSMSE) .... .............................. 08

- Stored Procedures no SQL Server............................................................. 12

- Colocando Resources dentro do executável ............................................. 17

- Dicas & Truques ........................................................................................ 20

- Perguntas & Respostas ............................................................................. 25

EditorialCaros Leitores,

Nesta edição traremos um pouco mais de informações e dicas de como trabalhar com Recursos no Delphi e outra ma-téria denominada “SQL Server Management Studio Express”, contendo exemplos de como trabalhar com esta ferramenta para gerenciamento do banco de Dados SQL Server. Ambas escritas pelo nosso consultor técnico Vitor Scarso.

Nossos colaboradores não ficam por fora, Mauro Santana finaliza sua série de artigos “Novidades da Linguagem C#” e Jones Amaral traz outra muito útil chamada “Testes compor-tamentais: psicologia ou tecnologia?”.

Continuando nossa seqüência de matérias sobre o SQL Serv-er, nosso consultor técnico Thiago Cavalheiro Montebugnoli vem com uma ensinando a trabalhar com os denominados Procedimentos Armazenados chamada “Stored Procedure no SQL Server”.

E para finalizar, não deixem de conferir nossa seção de “Dicas & Truques” e “Perguntas & Respostas”.

Boa Leitura a todos.

Novidades na linguagem

04

Novidades na

Linguagem

Parte 4

Esta é a quarta parte da série sobre novidades na linguagem no .NET Framework 3.5, conforme presente no Visual Studio 2008 Beta 2.

LINQ

O objetivo principal do LINQ é aproximar dois mundos presentes no desenvolvimento de software que são relativamente separados: o mundo das linguagens de programação e o dos bancos de dados, especialmente os bancos de dados relacionais.

Os principais problemas endereçados pelo LINQ são os seguintes:• As consultas de banco de dados relacionais são baseadas em

strings, que são quase como “corpos estranhos” em relação ao resto dos elementos das linguagens de programação. A manipulação de strings é sujeita não só a erros, usualmente descobertos apenas em tempo de execução, como também a um grave problema de segurança chamado “injeção de SQL”.

• Os conjuntos de resultados retornados pelas consultas voltam em um formato que deve ser traduzido de alguma forma para s linguagem de alto nível.

O LINQ consolida as novidades discutidas anteriormente de forma a facilitar o acesso a banco de dados, permitindo expressões semelhantes às linguagens de quarta geração, mas sem abandonar as linguagens OOP tradi-cionais. Com o LINQ podemos efetuar uma consulta em uma base de dados com um comando semelhante ao seguinte:

IEnumerable<string> query = from s in Nomes where s.StartsWith(“A”) orderby s select s.ToUpper();

Um exemplo simplesSuponha que tenhamos a seguinte classe:

class Linq1{ static string[] Nomes = { “Antonio”, “Amanda”, “Bruno”, “Frederico”, “Alber-to”, “Jorge”, “Mauricio”, “Ademar” }; static void Mostra(IEnumerable<string> query) {

foreach (string item in query) Console.WriteLine(item); } private static void Exp1() { Console.Write-Line(“>>>>>>>>>>>>>>>>>>>>>>>> Exp1”); IEnumerable<string> query = Nomes.Where(s => s.StartsWith(“A”)); Mostra(query); } static void Main() { Exp1(); }}

Note que no método Exp1 estamos usando um Extension Method chama-do “Where” para o qual passamos a expressão lambda “s => s.StartsWith(“A”)” para especificar o critério de seleção.

Podemos adicionar ao resultado uma chamada a outro Extension Method, “OrderBy” passando a expressão lambda “s => s” de forma a ordenar o resultado:

private static void Exp2() { Console.Write-Line(“>>>>>>>>>>>>>>>>>>>>>>>> Exp2”); IEnumerable<string> query = Nomes.Where(s => s.StartsWith(“A”)); query = query.OrderBy(s => s); Mostra(query); }

Adicionaremos outra chamada a um Extension Method que dirá o que selecionamos, no caso os dados convertidos para maiúsculo:

private static void Exp3() {

novidades na linguagem

05

Sobre o autor

Console.Write-Line(“>>>>>>>>>>>>>>>>>>>>>>>>>>> Exp3”); IEnumerable<string> query = Nomes.Where(s => s.StartsWith(“A”)); query = query.OrderBy(s => s); query = query.Select(s => s.ToUpper()); Mostra(query); }

Evidentemente podemos colocar tudo em uma única linha de código:

private static void Exp4() { Console.Write-Line(“>>>>>>>>>>>>>>>>>>>>>>>>> Exp4”); IEnumerable<string> query = Nomes.Where(s => s.StartsWith(“A”)).OrderBy(s => s).Select(s => s.ToUpper()); Mostra(query); }

O C# 3.0 tem uma novidade chamada “query expressions” que permite escrever a linha de código acima de uma forma mais elegante, usando novos operadores que mapeiam para os extension methods acima. Com estes novos operadores, o código fica assim:

private static void Exp5() { Console.Write-Line(“>>>>>>>>>>>>>>>>>>>>>>>>> Exp5”); IEnumerable<string> query = from s in Nomes where s.StartsWith(“A”) orderby s select s.ToUpper(); Mostra(query); }

LINQ to SQL

Evidentemente a maior parte dos dados estará em bancos de dados SQL. Portanto, é interessante termos uma maneira de mapear a expressão LINQ para uma chamada SQL submetida a um servidor.

Para isso precisamos inicialmente definir uma classe que armazenará os dados retornados pela query. Esta classe deve ter um campo para cada coluna da query e atributos adequados, como por exemplo:

[Table(Name = “Products”)]public class Products

{ [Column] public int ProductID { get; set; } [Column] public string ProductName { get; set; } [Column] public int? CategoryID { get; set; }}

Depois precisamos criar um “DataContext”, que basicamente contém uma string de conexão SQL para um SQL Server. Depois disso chamamos o método GetTable que retorna uma referência a uma Tabela que será usada posteriormente na query LINQ, como mostrado a seguir:

static void Main(){ DataContext context = new DataContext(@”Initial Catalog=Northwind;Integrated Security=sspi”); Table<Products> Prods = context.GetTable<Products>(); var q = from c in Prods where c.CategoryID == 1 select c; foreach (Products P in q) { Console.WriteLine(P.ProductName); }}

A criação do comando SQL é feita dinamicamente e a query é executada apenas no momento em que os dados são lidos na chamada a foreach.

A classe DataContext é específica para o Microsoft SQL Server, mas já foram anunciadas classes similares para outros bancos de dados como Oracle, Postgres e MySSQL.

Colclusão

O uso do LINQ permite a criação de código de maneira mais fácil que o cor-respondente código ADO.NET.e representa sem dúvida uma grande inovação em recusros em uma linguagem de programação de uso amplo.

Mauro Sant’Anna nunca trabalhou na Microsoft, mas con-hece bastante a empresa, já que é MVP e “Regional Director of the Year”. Ele coordena os cursos na M. A. S. Informática (www.mas.com.br) e bloga em Português em http://blogs.vstsrocks.com.br e em inglês em http://maurosjungle.spaces.live.com .

testes comportamentais

06

TESTES COMPORTAMENTAIS:

PSICOLOGIA OU TECNOLOGIA?

Com a crescente demanda de testes, passamos a olhar para um novo prisma o que temos chamado de Testes Comportamentais. Falando assim você pode pensar: ”_ desde quando uma aplicação

apresenta comportamento diferente para que eu teste isso? - Certamente eu te respondo: a aplicação não se comporta de maneira diferente, mas as pessoas que irão usá-la sim. Cada um usará do seu próprio jeito”.

Há algum tempo os testes em software não são bem aceitos, principal-mente por desenvolvedores e surpreendentemente por algumas empresas. De um lado as empresas afirmam que é um investimento sem retorno visível e que o tempo gasto para testar uma aplicação, aumentaria o tempo total do projeto. Isso é a última coisa que um cliente quer. Pelo lado dos desenvolve-dores, nem sempre há uma relação “amigável” com analistas de testes, pois, segundo eles, os analistas irão auditar os trabalhos e isso pode comprometer a imagem do “bom” desenvolvedor.

Percebe-se, timidamente, que a aceitação dos testes em software estão mudando. Notamos que a cada dia fica mais clara a relevância de testes em software, entretanto com antecipação nos preocupamos com as expectativas dos clientes que são geradas quando se iniciam formalmente processos de teste e qualidade. Estes pontos de apreensão, resumidamente, destacam-se em:

• O desenvolvedor reduz sua atenção na codificação quando ex-istem processos de testes, em outras palavras, há uma redução inicial da qualidade;

• Testes automatizados não cobrem problemas óbvios de usabilidade e ergonomia, ou seja, não atendem requisitos do usuário final;

• Testes de caixa preta (Black Box) não ajudam a identificar o ponto onde ocorre o problema no código fonte e por isso é demorado de ser re-solvido, o que geralmente atrasa o desenvolvimento do projeto;

• O trauma gerado por um erro descoberto em produção é centenas de vezes maior quando existe um processo formal de testes comparado a quando não existe. Sendo assim, o risco de uma área de testes ser cancelada no inicio de suas atividades é crítico;

Com base em todo o cenário descrito, averiguamos na prática que os resultados alcançados quando utilizamos somente testes automatizados e / ou testes de caixa preta não atendem as expectativas dos usuários de negócios da nossa aplicação. Por isso utilizamos testes comportamentais.

Testes comportamentais têm como foco o usuário, ou seja, os testes são aplicados de modo a mostrar como diferentes tipos de usuários preencheriam um formulário. Por exemplo, de que modo esse usuário normalmente irá acessar uma aplicação?

A metodologia de testes comportamentais é composta por três segmentos conceituais. São eles: Testes de verificação, testes de validação e testes de especialização. Esta metodologia de testes não descarta nenhum dos métodos até hoje conhecidos, simplesmente transcende-os valorizando-os.

Iremos apresentar um pouco sobre cada um deles mostrando como aplicamos estes testes visando o comportamento de quem usa essa aplicação a ser testada.

Testes de Usabilidade

A aplicação é usável, intuitiva, simples? _ Nem sempre. Visando essa us-abilidade citada testamos a praticidade da aplicação, o caminho que o usuário deverá seguir até conseguir o resultado esperado. Achamos possíveis “pedras” neste caminho, que ora chamaremos de inconsistências e apontaremos isso no que definimos de planilha de inconsistência.

Definição Básica: Assegurar que o produto tem condições de ser usado.

Testes de Especificação

Quando você chega ao Mc Donald´s, por exemplo, e pede pelo número 1 você espera que lhe entreguem um Big Mac. Quando um cliente solicita uma aplicação, ele espera que quando acessar ela pronta, ela irá fun-cionar da maneira que ele imaginou em sua mente. Visando isso, aplicamos os testes de especificação.

Agora, se um cliente chega ao Mc Donald´s e pede o mesmo número 1 só que sem alface, isso se torna uma nova especificação. Também verificaremos estas regras solicitadas pelo cliente, certamente descritas na documentação da aplicação.

Definição Básica: Assegurar que as especificações foram atendi-das.

Este primeiro grupo de testes (usabilidade e especificação) chama-

testes comportamentais

07

Sobre o autorJones Amaral é analista de testes e qualidade da MZ-IR.

Aplica testes comportamentais há um ano e é responsável pelo controle de qualidade de 23 sistemas diferentes desenvolvidos internamente na empresa.

remos de Testes de Verificação.

Testes de Funcionalidade

Qual é a premissa básica de uma calculadora? Obviamente que calcular. Quando eu digitar 1+1 ela tem que me mostrar o resultado: 2. Qual é a premissa básica da aplicação que você está testando? É esta premissa que iremos validar nos testes de funcionalidade.

Exemplo: Um usuário tem que preencher um formulário. O sistema tem que enviar essas informações para serem armazenadas em um banco de dados e ao mesmo tempo enviar as informações por email para alguém. Não podemos dizer que esta aplicação esta validada se a informação for guardada no banco de dados. E o email? Caso o e-mail não seja enviado, afirmaremos que a aplicação não esta estabilizada.

Definição Básica: Assegurar que o sistema está atendendo suas premis-sas de negócios.

Testes de Regressão

A aplicação está em seu quinto release, será que tudo aquilo que foi verificado como inconsistência no primeiro ou segundo release continua corrigido? Pegaremos todas as planilhas de inconsistência a partir do primeiro release e checaremos inconsistência por inconsistência para garantir que erros que apareceram no primeiro release não voltarão a acontecer.

Chamaremos isso de teste de regressão. Voltar no tempo e validar tudo que já foi validado. Retrabalho? Perda de tempo? Não! Garantia de que a aplicação irá ser entregue 100% sem reincidências.

Definição Básica: Eliminar reincidência de erros conhecidos e versões posteriores.

Desta forma encerramos o segmento denominado de Testes de validação.

Apresentamos o último grupo de testes da metodologia testes comportamentais, conhecido como Testes de Especialização. Este é o grupo que mais tem haver com o nosso tema, pois é nele que a personalização e a valorização do usuário é mais focada.

Testes de Cenário

“_ Estou utilizando o Internet Explorer 7 e meu estagiário esta utilizando o Mozilla Firefox. A aplicação funciona na minha máquina mas não na dele, por quê isso?” Essa é uma pergunta que acontece ainda muitas vezes. A resposta pode parecer simples: Isso acontece porque a aplicação não foi testada em diversos cenários.

O uso de máquina virtual neste tipo de teste é muito importante, porque o analista de teste pode montar “n” máquinas virtuais com “m” nav-egadores diferentes e checar como a aplicação se comporta em diferentes ambientes. Afinal cada usuário tem uma configuração diferente em seu

personal computer, e, se é pessoal, não podemos esperar que sejam todos iguais.

Definição Básica: Diagnosticar o comportamento do produto sobre determinado cenário.

Testes de Persona

O diretor da empresa que acabara de comprar sua aplicação pref-ere fazer login através do menu de usuários. Já o analista, prefere fazer login através do formulário que é carregado junto com a página inicial. Cada um percorre um caminho diferente, cada um utiliza a aplicação de uma maneira própria.

Pensando na resolução de conflitos, qual dos usuários acima geram mais risco para nossa aplicação no caso da função de login possuir erros?

Definindo perfis criamos grupos de usuários e escrevemos um documento com estas características de utilização. Neste documento estará descrito como cada grupo de usuários utiliza a aplicação e o modo como utiliza. Assim, quando houver liberação de uma nova versão da aplicação, podemos, por meio do perfil, navegar pelo caminho que o usuário de um determinado perfil percorre a fim de encontrar inconsistências ou vulnerabilidades que o usuário encontraria. Deste modo, personalizamos os testes.

Definição Básica: Atender expectativas direcionadas de “stakehold-ers”.

Porque testes comportamentais

Agora que já sabemos a definição de cada um dos tipos de testes pertencentes a metodologia chamada Testes Comportamentais, entendemos o objetivo dos mesmos: focar nossas atividades no usuário e agregar valor a nossas aplicações.

Nós acreditamos no valor insubstituível do usuário na hora de testar um sistema, simplesmente porque testes comportamentais introduzem valores do usuário no sistema e revelam novos problemas que não são descobertos por testes automatizados.

Referências e informações sobre testes comportamentais podem ser obtidas no site http://www.fcamara.com.br

Bons testes,

SQL Server

08

SQL Server Management Studio Express (SSMSE)

Muitos sócios desconhecem ou não sabem como tirar proveito dessa incrível ferramenta voltada para o SQL Server 2005 Express.

O SSMSE fornece ao desenvolvedor e administrador do banco de dados um conjunto de ferramentas que facilitam e agiliza o trabalho. Existem duas versões para essa ferramenta assim como o SQL Server. A versão Express (SSMSE) que vamos destacar nessa matéria e a SSMS, voltada para a versão paga do SQL SERVER.

Essa é uma ferramenta gráfica amigável que possui recursos magníficos como “Database”, “Table Designer”, “Query Editor”, “Object Explorer”, “Tem-plate Explorer” e outros. A maioria dos recursos é facilmente acessado pelo simples clique do botão direito do mouse, também é possível usar scripts para executar diversas tarefas facilitando o trabalho.

O primeiro passo é adquirir essa ferramenta que esta disponível no site da Microsoft – (www.microsoft.com.br), na sessão download procure pelo nome: “Microsoft SQL Server Management Studio Express”.

A instalação é bem simples basta executar o arquivo que foi baixado e seguir as orientações da tela, NEXT... NEX... NEXT.

Como conectar ao Servidor

Figura 01- Tela de logon com o SqlServer

Conforme mostra a “figura 01” essa é a tela que aparece quando entramos no SQL MANAGEMENT para podermos conectar com o nosso Servidor. Veja mais informações sobre as opções disponíveis:

“Server Type”: mostra os tipos de servidores disponíveis no micro, que no nosso caso é somente o “Database Engine” do SQLSERVER.

“Server Name”: é possível escolher em que banco de dados se conectar e o método de rede (TCP/IP, Named Pipes) para utilização. Seguido pelo nome da instância que foi instalada no servidor. No nosso exemplo a instância SQLExpress se encontra na máquina VITOR.

“Authentication”: Com essa opção você decide se deseja conectar direta-mente com o Banco de Dados por meio da opção “SQL Server Authentication” ou se preferir usar o Windows Authentication. O Windows Authentication utiliza as credenciais da conta Microsoft Windows® que está sendo executada. O SQL Server Authentication utiliza um nome de usuário e senha fornecidos pelo SQL Server fora da infra-estrutura de segurança do Windows. O Windows Authentication é mais fácil para o uso dos usuários de banco de dados porque é automático; nenhum login especial ou senha são exigidos. Por padrão, ela está definida em Windows Authentication.

Figura 02 – Opções Avançadas de conexão

SQL Server

09

Na aba “Connection Properties” (mostrado na figura 02) pode alterar algumas configurações da conexão que será estabelecida com o Banco de Dados. Opções como “Connect to Database” que tem por objetivo definir qual banco de dados ira trabalhar inicialmente. A opção “Network Protocol” define qual protocolo será usado (Memória Compartilhada,TCP/IP,Named Pipes). “Network Packet Size” define o tamanho do pacote de dados transmitido pela rede, altere conforme a necessidade de sua rede. “Connection time-out” define o tempo de espera pela resposta do servidor, altere somente se não tiver uma resposta rápida do seu servidor.

Depois de feita a conexão...

Depois de feita a conexão com o banco de dados irá abrir uma tela semelhante as outras IDEs de manutenção de Banco de Dados (IBExpert, IBConsole etc). É dividido em “partes”. Na parte superior tem os menus, na parte a esquerda o “Object Explorer” (veja a figura 03). Vamos destacar cada parte do SSME para poder aprender ao máximo dessa ferramenta.

Figura 03 – Ambiente do aplicativo SSMSE

Object Explorer

O Object Explorer exibe to-dos os objetos envolvidos de determinado banco. Por meio do login, o privilégio de usuários, é que determinamos se temos acesso/visualizar a determina-dos componentes. Na figura 04 podemos ver que é dividido em chaves: Databases, Security, Server Objects, Managmement, Replication.

Figura 04 – Objetos do Banco de Dados visualizado pelo Object Explorer

Não vamos aprofundar em cada objeto ou item disponível por essa ferramenta, senão a matéria se tornaria muito extensa. Porém vamos desta-

car as opções mais úteis e usadas para administrar o Banco de Dados SQL SERVER 2005.

Databases: Mostra as Databases que estão registradas no servidor, jun-tamente com os objetos de cada um. Em nosso exemplo temos dois bancos registrados pelo usuário: Exemplo e Northwind. Os outros objetos são criados pelo SQL Server para serem usados para gerenciar os processos do sistema. Se abrirmos o BD Northwind poderemos visualizar todos os seus objetos como: Tables (Tabelas), Views(Visões), Programmability (Programabilidade) etc. Veja a figura 05. Na chave Progammability podemos visualizar as Stored Procedures, Functions, Triggers, Assemblies (Montagem), Types (Tipos), Rules (Regras).

Figura 05 – Objetos do BD Northwind

Com a facilidade do mouse podemos criar uma tabela ou uma stored procedure somente clicando com o botão direito do mouse sobre o objeto correspondente. Opções como exclusão e Atualizar (Refresh) também estão disponível para poder facilitar a manutenção do banco de dados.

Security: Essa parte é designada a segurança do Banco. Veja a figura 06. Nessa chave encontramos as opções Logins (Para adicionar usuários e seus privilégios), Server Roles (Regras do Servidor), Credentials (Credenciais).

Figura 06 – Chave Security

Server Objects: Mostra os Objetos internos do servidor como: Backup Devices (Para fazer backup da Database. Linked Servers (Para criar links com o servidor podendo ser remoto). Server Triggers (Triggers internas do Servidor)

SQL Server

10

Figura 07 – Chave Server Objects

Como criar um BD

É possível criar e registrar uma BD somente com instruções SQL por meio do SQL Editor. Porém é muito mais fácil usar a interface disponível pelo SQL Management Express, somente com alguns cliques do mouse. Clique com o botão direito na pasta “Database” e escolha a opção New Database (veja figura 08 ).

Figura 08 – Tela para criação do DB

Nessa tela é possível definir o nome do Banco de Dados (Database Name), o proprietário (Owner), que no nosso caso vai ser o SA. O interessante nessa tela que também podemos definir o nome e o tamanho do arquivo LOG (para mais informações veja a matéria 11/07 falando sobre “Transation Log”). A guia Options contém configurações avançadas que poderá melhorar o desem-penho do seu BD. A configuração padrão é uma boa opção para a maioria das situações. Depois de definido as configurações basta clicar no botão OK para concluir a operação.

Como criar Tabelas

Abrindo a pasta do DB TheClub que acabamos já podemos criar as tabe-las. Clique com o botão direito do mouse em cima da pasta Table e escolha a opção New Table (veja a figura 09).

Figura 09 – Criando tabelas

Nessa tela é possível adicionar os nomes dos campos e seus tipos. Do lado direito irá abrir uma “janela” informando as propriedades da tabela como nome, schema ao qual pertence proprietário etc. Na parte inferior temos a janela Column Properties que são as propriedades das colunas. Quando fechar a janela o programa irá perguntar se deseja salvar a tabela.

Nota: Para mais informações sobre qual tipo de campo deve escolher veja a seção DICAS E TRUQUES da revista de janeiro de 2008 com o título – Tipos de Dados no SQL Server 2005

TEMPLATES

Outro recurso muito interessante é o uso dos TEMPLATES. Que são rotinas pré-montadas com o objetivo de aumentar a produtividade do nosso trabalho. Para visualizar os templates basta acessar o menu VIEW->TEMPLATE EXPLORER. Veja a figura 10.

Figura 10 – Template Explorer

Clique na pasta Backup irá abrir três opções, escolha a primeira Backup Database, logo após vai aparecer a tela de login novamente e veja que toda a instrução necessária (SQL) já estará montada. Depois só altere as informações conforme necessário.

-- ===========================-- Backup Database Template-- ===========================

sql server

11

Sobre o autor

HUMOR

BACKUP DATABASE <Database_Name, sysname, Database_Name> TO DISK = N’<Backup_Path,,C:\Pro-gram Files\Microsoft SQL Server\MSSQL.1\MSSQL\Backup\><Database_Name, sysname, Database_Name>.bak’ WITH NOFORMAT, NOINIT, NAME = N’<Database_Name, sysname, Database_Name>-Full Database Backup’, SKIP, STATS = 10;GO

Na pasta Database contém a maiorias das operações que serão executadas referentes aos DB, como: registrar, apagar,criar etc (Veja a figura 11). Veja as instruções Attach Database, para registrar um banco de dados já existente:

--=====================================-- Attach database template--=====================================IF NOT EXISTS( SELECT * FROM sys.databases WHERE name = N’<database_name, sys-name, your_database_name>’) CREATE DATABASE <database_name, sys-name, your_database_name> ON PRIMARY (FILENAME = ‘<da-tabase_primary_file_path,,C:\Program files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\your_database_name.MDF>’) FOR ATTACHGO

Figura 11 – Template Explroer – Database

Conclusão

O SQL MANAGEMENT EXPRESS é uma ferramenta fácil e intuitiva de usar. Facilita em muito o trabalho do Administrador do Banco de Dados. Destaquei de uma forma breve e rápida o uso dessa ferramenta, porém ela possui recursos avançados que pode facilitar ainda mais a manutenção do banco de dados. Mas isso irei deixar para um próximo artigo.

Um abraços a todos e até a próxima!

Vitor Scarso é consultor técnico do The Club, trabalha com programação há 5 anos e é formado em Técnico de Informática pela CNEC – Capivari.

Querida, o Windows travou novamente!!!

Crianças, vão ajudar o papaipressionar “CTRL + ALT + DEL”!

stored procedures

12

Stored Procedures no SQL Server

O que é uma Stored Procedure?

Iremos definir de uma forma prática e objetiva. As denominadas “Stored Procedures” (Procedimentos Armazenados) como o próprio nome diz, é uma seqüência de comandos SQL compilados e armazenados no Banco de Dados.

Tipos de Stored Procedures

Nesta matéria abordaremos os dois principais tipos de Stored Procedures no SQL Server, System Procedures (Procedimentos Armazenados do Sistema) e User Stored Procedures (Procedures Locais ou de Usuários). É importante salientar que existem outros dois tipos de Stored Procedures, as Procedures Temporárias e as Estendidas, esta última é implementada como uma DLL, mas neste artigo falaremos um pouco das duas primeiras.

Utilizando o Banco de Dados Northwind

Utilizaremos o Banco exemplo Northwind para trabalhar nesta matéria, para quem não possui instalado poderá ser baixado gratuitamente pelo site da Microsoft, no seguinte link:

http://download.microsoft.com/download/d/e/5/de57f203-3140-43e0-9473-d694d45bbd9b/SQL2000SampleDb.msi

Depois que rodarmos este executável, por padrão, será criado uma pasta no seguinte diretório:

C:\SQL Server 2000 Sample Databases

Copie os arquivos NORTHWND.LDF (Arquivo de Log) e NORTHWND.MDF (Arquivo de Dados) para a pasta padrão:

C:\Arquivos de programas\Microsoft SQL Server\MSSQL.1\MSSQL\Data

Utilizaremos a ferramenta padrão do SQL Server chamada “SQL Server Management Studio Express” para podermos registrar o Banco de Dados

NorthWind. Depois de aberto este gerenciador, encontrará uma janela idên-tica com a Figura 01.

Figura 01. SQL Server Management Studio Express.

Na região esquerda registraremos o banco NorthWind, para isto clique com o botão direito em “Databases” e escolha Attach...No botão Add adi-cionaremos o arquivo NorthWind.MDF e automaticamente será incluído o NorthWind.LDF, logo após dê um ok para finalizar esta operação. Veja Figura 02 e 03.

Figura 02. Registrando o Banco de Dados.

stored procedures

13

Figura 03. Banco de Dados NorthWind.

Observe: Caso já possua o Banco Registrado não é necessário realizar os passos descritos acima.

Executando Stored Procedures

Podemos utilizar o comando abaixo:

execute nome_da_SP parâmetro 1, parâmetro 2, etc...

ou apenas a abreviação

exec sp_nome_da_SP parâmetro 1, parâmetro 2, etc...

System Procedures

As System Procedures são armazenadas no Banco de Dados, no nosso caso no Database Nortwind (vide Figura 04 ). Elas são iniciadas pelo prefixo sp e são criadas automaticamente na instalação do SQL Server. Logo abaixo abordaremos algumas das principais Stored Procedures para um melhor entendimento:

Figura 04. System Stored Procedures.

sp_databases

Este procedimento é útil para mostrar os nomes dos Databases existentes no servidor.

exec sp_databases

Teremos um resultado parecido com o da Figura 05.

Figura 05. sp_databases.

sotored procedure

14

sp_columns

Retorna informações das colunas de tabelas ou views.

Sp_columns [@table_name=] nome_objeto [, [@table_owner =] nome_dono] [, [@table_qualifier =] nome_ban-co] [, [@column_name =] nome_coluna] [, [@ODBCVer =] verODBC]

Argumento Descrição@table_name Nome da tabela ou View

@table_owner Nome do dono da tabela

@table_qualifier Nome do banco de dados

@column_name Nome da coluna

@ODBCVer Versão da ODBC utilizada

Se desejarmos retornar todos os campos de uma determinada tabela utilizaremos o comando abaixo:

exec sp_columns categories

Figura 06. Retornando os campos da tabela Categories.

Podemos também verificar se um campo existe na tabela Categories.

execute sp_columns Categories, dbo, Northwind, CategoryID

Neste caso verificaremos se o campo CategoryID existe no Banco de Dados NorthWind.

sp_tables

Retorna a lista de tabelas e visões que podem ser utilizados no ambiente atual.

Sp_tables [[@name=] ‘nome_objeto’] [,[@owner =] ‘nome_dono’] [,[@qualifier =] ‘nome_bd’]

Argumento Descrição@name Nome da tabela ou View

@owner Nome do dono da tabela

@qualifier Nome do banco de dados

Retornando todos os objetos

exec sp_tables

Figura 07. Retornando as tabelas.

Agora passaremos os parâmetros para verificarmos se a tabela ou a visão existe em determinado Database.

exec sp_tables Categories, dbo, Northwind

sp_stored_procedures

Esta retorna a lista de Stores Procedures no ambiente corrente.

stored procedure

15

sp_stored_procedures [[@sp_name=] ‘nome_da_procedure’] [,[@sp_owner =] ‘nome_dono’] [,[@sp_qualifier =] ‘nome_bd’]

Argumento Descrição@sp_name Nome da Procedure

@sp_owner Nome do dono da Procedure

@sp_qualifier Nome do banco de dados

Retornando todas as Procedures

exec sp_stored_procedures

Figura 08. Retornando as SP.

Verificando se determinanda procedure existe na Base de Dados.

exec sp_stored_procedures CustOrderHist, dbo, Northwind

Importante ressaltar que o Banco de Dados Sql Server possui diversas Procedures de Sistemas e que são muito úteis na utilização de nossos sistemas. Este é um recurso muito interessante deste Banco de Dados, nesta parte da matéria procurei demostrar exemplos práticos de algumas das principais System Procedures.

User Stored Procedures (USP)

Os denominadas Procedimentos de usuários são criados no Banco de Da-dos para utilização do sistema. Uma nomenclatura recomendada para criação

dos mesmos seria a utilização do prefixo “usp_” . O uso de nomenclaturas é um princípio geralmente ignorado pela maioria das pessoas, mas que é altamente recomendado, pois servirá para a distinção em relação aos outros tipos de Stored Procedures encontradas. Um exemplo disto é a padronização no nome das System Procedures, são iniciadas pelo prefixo sp_.

Criando uma “Stored Procedure”

Para Criarmos uma Stored Procedure deveremos seguir o modelo abaixo:

create procedure <Nome da procedure>

<Onde irão os parâmetros de entrada seguido do tipo de campo> as

< Irá a instrução SQL, caso possui um retorno o mesmo será o resultado da ex-ecução da Stored Procedure>

Seguindo o modelo acima, montaremos uma Stored Procedure que possui um parâmetro de Entrada e como retorno o resultado do comando select.

Procedure de Seleção

create procedure usp_BuscaCliente@nome varchar(50) as select * from dbo.Customerswhere ContactTitle like ‘%’ + @nome + ‘%’

Notem que o parâmetro de Entrada é precedido do caracter @.

Para executá-la:

exec usp_BuscaCliente ‘Owner’

A Figura 09 demonstra o retorno da execução do procedimento usp_Bus-

stored procedure

16

Sobre o autorThiago Cavalheiro Montebugnoli é tecnólogo, formado

pela Faculdade de Tecnologia de Botucatu – SP (FATEC) e consultor técnico do The Club.

caCliente.

Figura 09. Retorno da USP.

Procedure de Inserção

Criaremos uma Stored Procedure para inserir registros na tabela Cus-tomers, neste caso iremos inserir apenas em três campos, veja abaixo como ficaria:

create procedure usp_InsereCliente@ID nchar(5), @Company nvarchar(40), @Contact nvarchar(30) as Insert into Customers (CustomerID, Compa-nyName, Contactname)values(@ID, @Company, @Contact)

Para executá-la:

exec usp_InsereEmpregado 10000, ‘THE CLUB’, ‘THIAGO CAVALHEIRO MONTEBUGNOLI’

Procedure de Deleção

Excluiremos os registros cujo ID é informado pelo parâmetro de en-trada.

create procedure usp_ExcluiCliente@ID nchar(5) as delete from Customers where CustomerID = @ID

Para executá-la:

exec sp_excluicliente 10000

Procedure de Atualização

Atualizamos o registro ContactName para Null cujo ID é informado por parâmetro de entrada

create procedure usp_AtualizaCliente@ID nchar(5) as Update Customers set ContactName = null where CustomerID = @ID

Para Executá-la:

exec usp_atualizaCliente 10000

Conclusão

Vimos nesta matéria os dois principais tipos de Stored Procedure exis-tente no SQL Server, verificando alguns exemplos práticos de sua utilização. Finalizo esta matéria dizendo que a utilização de Stored Procedures é sempre uma boa idéia.

Sucesso a todos e até a próxima!

Resources

17

É possível embutir arquivos dentro de um executável por meio dos arquivos resources (Rescursos - *.RES). Todos os arquivos adicio-nados são organizados e podem ser acessados diretamente por

API. Este artigo vem com o objetivo de orientar como adicionar arquivos no resource e acessá-los.

Para começar a criar um arquivo resource, iniciaremos com o arquivo (*.RC), que em nosso exemplo vem com o nome RECURSOS.RC. Trata-se de um simples arquivo de texto contendo o nome do recurso, classe e o nome do arquivo físico, veja o exemplo abaixo:

RECURSOS.RC

sample_bmp BITMAP sample.bmp sample_ico ICON sample.ico sample_cur CURSOR sample.cur sample_ani ANICURSOR sample.ani sample_jpg JPEG sample.jpg sample_wav WAVE sample.wav sample_txt TEXT sample.txt

Os nomes da primeira e terceira coluna podem ser escolhidos de acordo com a vontade do programador, somente a coluna do meio que tem que respeitar a classe do arquivo.

Após os nomes serem especificados iremos adicionar ao nosso executável.Vamos compilar o arquivo .RC para transformá-lo em .RES (resource).

Para isso usaremos o “Borland Resource Compler” (brcc32.exe), que provavelmente vem junto com o Delphi na pasta BIN. Usando uma simples linha de comando no DOS podemos compilar o nosso arquivo, veja o ex-emplo:

C:\DELPHI >brcc32 recursos.rc

Borland Resource Compiler Version 5.40 Copyright (c) 1990, 1999 Inprise Corporation. All rights reserved.

Colocando Resources

dentro do executável C:\DELPHI >_ Pronto! Se não exibir mensagem de erros é porque a estrutura do arquivo

foi digitada corretamente.

Como adicionar o recurso nos projetos Delphi?

Para linkar e embutir o recurso no executável nós usaremos a diretiva ($R ou $RESOURCE) no código fonte, veja o exemplo:

var Form1: TForm1;

implementation

{$R recursos.res}

end.

Quando compilamos nosso projeto automaticamente o arquivo recursos.res é adicionado ao executável.

Carregando Imagem Bitmap

Image1.Picture.Bitmap.Handle := LoadBitmap(hInstance, ‘sample_bmp’);

Carergando um ícone

Icon.Handle := LoadIcon(hInstance, ‘sam-ple_ico’);

Resources

18

Caregando um cursor Animado

constcnCursorID1 = 1;begin Screen.Cursors[1] := LoadCursor(hInstance, ‘sample_cur’); Cursor := cnCursorID1;

Carregando Imagem JPEG

{Declare a unit JPEG na cláusula uses}

function GetResourceAsJpeg(const resname: string): TJPEGImage; var Stream: TResourceStream; begin Stream := TResourceStream.Create(hInstance, ResName, ‘JPEG’); try Result := TJPEGImage.Create; Result.LoadFromStream(Stream); finally Stream.Free; end; end;

Exemplo

var Jpg: TJPEGImage; begin // ... Jpg := GetResourceAsJpeg(‘sample_jpg’); Image2.Picture.Bitmap.Assign(Jpg); Jpg.Free; // ... end;

Para arquivos de áudio (.WAV) precisaremos carregá-lo em memória, e arquivos texto em uma string. Veja os exemplos abaixo:

function GetResourceAsPointer(ResName: pchar; ResType: pchar; out Size:

longword): pointer; var InfoBlock: HRSRC; GlobalMemoryBlock: HGLOBAL; begin InfoBlock := FindResource(hInstance, resname, restype); if InfoBlock = 0 then raise Exception.Create(SysErrorMessage(GetLastError)); size := SizeofResource(hInstance, InfoBlock); if size = 0 then raise Exception.Create(SysErrorMessage(GetLastError)); GlobalMemoryBlock := LoadResource(hInstance, InfoBlock); if GlobalMemoryBlock = 0 then raise Exception.Create(SysErrorMessage(GetLastError)); Result := LockResource(GlobalMemoryBlock); if Result = nil then raise Exception.Create(SysErrorMessage(GetLastError)); end;

function GetResourceAsString(ResName: pchar; ResType: pchar): string; var ResData: PChar; ResSize: Longword; begin ResData := GetResourceAsPointer(resname, restype, ResSize); SetString(Result, ResData, ResSize); end;

Exemplo de como carregar:

//Declarar uma variável global var sample_wav: pointer;

//Colocando em um evento do botão var size: longword; begin sample_wav :=

delphi

19

Sobre o autorVitor Scarso é consultor técnico do The Club, trabalha com

programação há 5 anos e é formado em Técnico de Informática pela CNEC – Capivari.

GetResourceAsPointer(‘sample_wav’, ‘wave’, size); end;

Uma vez carregado em memória podemos tocar o som quantas vezes desejarmos usando a API sndPlaySound declarado na unit MMSystem:

procedure TForm1.Button1Click(Sender: TObject); begin sndPlaySound(sample_wav, SND_MEMORY or SND_NODEFAULT or SND_ASYNC); end;

Para alguns tipos de resources (como fontes e cursores animados) não podemos usá-lo direto da memória. Precisamos salvar em arquivo, temporari-amente, e carregá-los conforme a necessidade. Veja a próxima função que salva um resource como arquivo:

procedure SaveResourceAsFile(const ResName: string; ResType: pchar;

const FileName: string); begin with TResourceStream.Create(hInstance, ResName, ResType) do try SaveToFile(FileName); finally Free; end; end;

Espero que essas dicas sejam úteis para muitos programadores. Um forte abraço e até a próxima!

Download

O exemplo referente a esta matéria está disponível para download no seguinte link (aqui irá o endereço do link do exemplo)

dicas & truques

20

Treeview – Realizando uma Busca Recursiva

Nesta dica iremos implementar uma busca recursiva utilizando o com-ponente Treeview, para isto adicione 3 botões e dois Treviews. O formulário deverá ficar parecido com a Figura 01.

Figura 01. Treeview – Busca Recursiva.

procedure TForm1.InsereFilhos(NoOrigem:TTreeNode;Nivel:Integer);varN:Integer;No,NoDestino:TTreeNode;begin No:=nil; NoDestino:=nil; {Se a origem é não nulo e seu nível é maior que o nível da raiz} if (NoOrigem <> nil) and (NoOrigem.level > Nivel) then begin if TreeView2.Items.Count = 0 then NoDestino := Treeview2.Items.

Add(No,NoOrigem.Text) else begin For N := 0 to TreeView2.Items.Count-1 do if TreeView2.Items[N].Text = No-Origem.Parent.text then begin No := TreeView2.Items[N]; NoDestino := Treeview2.Items.AddChild(No,NoOrigem.Text); end;//if end;//else NoDestino.ImageIndex := NoOrigem.ImageIndex; NoDestino.SelectedIndex := NoOrigem.SelectedIndex; NoOrigem:=NoOrigem.GetNext; InsereFilhos(NoOrigem,Nivel); end;// if principalend;

function TForm1.InserePais: Boolean;varExisteItem :Boolean;Pos,Cont : Integer;No : TTreeNode;Nos : array of TTreeNode;begin ExisteItem :=False; Cont:=0; Pos:=0; SetLength(Nos, 1); No := TreeView1.Selected; Nos[Pos]:= TreeView1.Selected; {Retornando na árvore até a raiz guar-dando todos os nos ascendentes}

dicas & truques

21

while No.Parent <> nil do begin SetLength(Nos, Pos+2); Inc(Pos); Nos[Pos]:=No.Parent; No:=No.Parent; end; No:= nil;

{ insere itens na segunda árvore} Pos:= High(Nos); while Pos >= 0 do begin {verifica existência de Item na ár-vore} while Cont < Treeview2.Items.Count do begin if Nos[Pos].Text = Treeview2.Items.Item[Cont].Text then begin if Nos[0].Text = Treeview2.Items.Item[Cont].Text then begin ExisteItem:=True; Cont:=Treeview2.Items.Count; end else begin No := Treeview2.Items.Item[Cont]; Dec(Pos); end; end; Inc(Cont); end;//while da Treeview

if not ExisteItem then begin No := Treeview2.Items.AddChild(No,Nos[Pos].Text); No.ImageIndex := Nos[Pos].Image-Index; No.SelectedIndex := Nos[Pos].Se-lectedIndex; Result:=False;//Item não existente end else

Result:=True;//Item já existente Dec(Pos); end;//while do Arrayend;

No botão “Mover” insira o seguinte código:

procedure TForm1.BitBtn1Click(Sender: TObject);varNoSel: TTreeNode;ExiteItem:Boolean;beginExiteItem:=False;NoSel := TreeView1.Selected; if TreeView1.Parent <> nil then ExiteItem:=InserePais; if (not ExiteItem) then InsereFilhos(NoSel.GetNext,NoSel.Level) else ShowMessage(‘Item(s) Existe na Ár-vore!’);end;

No botão “Todos” insira o seguinte código:

procedure TForm1.BitBtn2Click(Sender: TObject);begin if Treeview2.Items.Count = 0 then TreeView2.Items.Assign(TreeView1.Items) else ShowMessage(‘Item(s) Existe na Ár-vore!’);end;

e no último botão finalmente deixe sua propriedade Caption como “Limpar”

procedure TForm1.BitBtn3Click(Sender: TObject);begin

dicas & truques

22

TreeView2.Items.Clear;end;

Figura 02. Treeview em Run-time.

Como Apagar uma imagem do Timage

procedure TForm1.BitBtn1Click(Sender: TObject);begin Image1.Canvas.Brush.Color := clWhite; Image1.Canvas.Rectangle( 0, 0, Image1.Width, Image1.Height ); Image1.Picture.Bitmap.Assign(nil);end;

Como Criar Uma Caixa de Diálogo Personalizada Uti-lizando a Função Createmessagedialog

function TCMessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDl-gButtons; aColor: TColor = clInfoBk): Integer;begin with CreateMessageDialog(Msg, DlgType, Buttons) do try BorderIcons := []; Color := aColor; Result := ShowModal;

finally Free; end;end;

{Chamando a Função}

procedure TForm1.Button1Click(Sender: TObject);begin if TCMessageDlg(‘The Club!!!’, mtCon-firmation, [mbYes, mbNo]) = mrYes then TCMessageDlg(‘OK!’, mtInformation, [mbOk], clAqua);end;

Inserindo mais de uma linha na propriedade Caption de um Botão

{Coloque o código abaixo no evento Oncre-ate do Form}procedure TForm1.FormCreate(Sender: TOb-ject);var R : TRect; N : Integer; Buff : array[0..255] of Char;

begin with BitBtn1 do begin Caption := ‘Este exemplo mostra como colocar mais de uma linha no caption de um botão’; Glyph.Canvas.Font := Self.Font; Glyph.Width := Width - 6; Glyph.Height := Height - 6; R := Bounds(0, 0, Glyph.Width, 0); StrPCopy(Buff, Caption); Caption := ‘’; DrawText(Glyph.Canvas.Handle, Buff,StrLen(Buff),R, DT_CENTER or DT_WORDBREAK or DT_CALCRECT); OffsetRect(R,(Glyph.Width - R.Right) div 2, (Glyph.Height - R.Bottom) div 2); DrawText(Glyph.Canvas.Handle, Buff,

dicas & truques

23

StrLen(Buff), R, DT_CENTER or DT_WORD-BREAK); end;end;

Trabalhando com os Eventos OnDragDrop e OnDrag-Over (Arrasta e Solta)

Para este exemplo iremos utilizar os seguintes componentes: ListBox (Standard) e StringGrid (Additional), veja Figura 02.

Figura 03. Evento Drag and Drop.

Iremos alterar a propriedade DragMode para dmAutomatic dos dois componentes, para assim podermos arrastar os itens que estão contidos nos mesmos.

Alimentaremos o StringGrid com alguns valores através do evento OnAc-tivate do Formulário.

procedure TForm1.FormActivate(Sender: TObject);begin StringGrid1.Cells[1,1] := ‘10’; StringGrid1.Cells[1,2] := ‘20’; StringGrid1.Cells[1,3] := ‘30’; StringGrid1.Cells[1,4] := ‘40’; StringGrid1.Cells[2,1] := ‘50’; StringGrid1.Cells[3,2] := ‘60’; StringGrid1.Cells[4,3] := ‘70’; StringGrid1.Cells[5,4] := ‘80’;end;

Faremos o mesmo para o Listbox adicionando alguns itens em sua pro-priedade Items.

Insira o código abaixo no evento OndragOver do Listbox.

procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Bool-ean);begin {a variável booleana Accept diz se o componente é um da classe TStringGrid} Accept := (Source is TStringGrid);end;

Insira o código abaixo no evento OndragDrop do Listbox.

procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);var Col, Row: integer;begin {Estaremos adicionado no Listbox o item selecionado no Stringgrid }Col := StringGrid1.Col; Row := StringGrid1.Row; if Source is TStringGrid then begin ListBox1.Items.Add(StringGrid1.Cells[col,row]); StringGrid1.Cells[col,row] := ‘’; end;end;

Insira o código abaixo no evento OnDragOver do Stringgrid.

procedure TForm1.StringGrid1DragOver(Sender, Source: TOb-ject; X, Y: Integer; State: TDragState; var Ac

cept: Boolean);begin {a variável booleana Accept diz se o componente é um da classe TListBox} Accept := (Source is TListBox);end;

E por final codificaremos o evento OnDragDrop do componente String-

dicas & truques

24

grid.

procedure TForm1.StringGrid1DragDrop(Sender, Source: TOb-ject; X, Y: Integer);var Col, Row: integer;begin {Estaremos adicionando no Stringgrid o item selecionado no Listbox} if (Source is TListBox) then begin StringGrid1.MouseToCell(X, Y, Col, Row); StringGrid1.Cells[Col, Row] := List-Box1.Items[listbox1.Itemindex]; listbox1.Items.Delete(ListBox1.Ite-mIndex); end;

end;

Convertendo Números decimais para Romanos

Function DecimaisRomanos( Decimal: LongInt ): String;const Romans: Array[1..13] of String = ( ‘I’, ‘IV’, ‘V’, ‘IX’, ‘X’, ‘XL’, ‘L’, ‘XC’, ‘C’, ‘CD’, ‘D’, ‘CM’, ‘M’ );Arabics: Array[1..13] of Integer =( 1, 4, 5, 9, 10, 40, 50, 90, 100,400, 500, 900, 1000);

var i: Integer; scratch: String;beginscratch := ‘’; for i := 13 downto 1 do while ( Decimal >= Arabics[i] ) do begin Decimal := Decimal - Arabics[i]; scratch := scratch + Romans[i]; end;Result := scratch;end;

Para utilizá-la:

procedure TForm1.Button2Click(Sender: TObject);begin caption := DecimaisRomanos(2008);end;

Retornar Data por extenso

procedure TForm1.Button1Click(Sender: TObject);var NoDia : Integer; DiaDaSemana : array [1..7] of String; Meses : array [1..12] of String; Dia, Mes, Ano : Word; begin

{ Dias da Semana } DiaDasemana [1]:= ‘Domingo’; DiaDasemana [2]:= ‘Segunda-feira’;DiaDasemana [3]:= ‘Terça-feira’; DiaDasemana [4]:= ‘Quarta-feira’; DiaDasemana [5]:= ‘Quinta-feira’;DiaDasemana [6]:= ‘Sexta-feira’;DiaDasemana [7]:= ‘Sábado’;

{ Meses do ano }Meses [1]:= ‘Janeiro’;Meses [2]:= ‘Fevereiro’;Meses [3]:= ‘Março’;Meses [4]:= ‘Abril’;Meses [5]:= ‘Maio’;Meses [6]:= ‘Junho’;Meses [7]:= ‘Julho’;Meses [8]:= ‘Agosto’;Meses [9]:= ‘Setembro’;Meses [10]:= ‘Outubro’;Meses [11]:= ‘Novembro’;Meses [12]:= ‘Dezembro’;

DecodeDate (Now, Ano, Mes, Dia);NoDia:= DayOfWeek (Now);

Caption:= DiaDaSemana [NoDia] + ‘, ‘ + inttostr (Dia) + ‘ de ‘ + Meses [Mes]+ ‘ de ‘ + inttostr (Ano);

end;

perguntas e respostas

25

Pergunta: Gostaria de saber se vocês tem alguma matéria explicando como criar Server e cliente de webservice no Delphi? Estamos precisando disto por conta da Nota Fiscal Eletrônica.

Resposta: Este assunto já foi bastante abordado nas matérias ante-riores.

Introdução e exemplo prático:http://www.theclub.com.br/revista/webs1202.aspx

WebServices com Banco de Dados:http://www.theclub.com.br/revista/webs0206.aspx Consumindo WebService:http://www.theclub.com.br/revista/cons1007.aspx

Dúvida enviada por Alan Tacconi, Votuporanga – SP.

Pergunta: Gostaria de saber como faço para verificar se em um Dbedit uma parte é

string e a outra números?

Exemplo: No campo é digitado somente AAA1234 (placa de veículo) Queria fazer a verificação pra não digitar errado.

Resposta: É necessário “quebrar” o conteúdo deste Dbedit para fazer uma validação dos dados.

Veja abaixo o código para fazer isto.

procedure TForm1.Button2Click(Sender: TObject);var text1,text2 : string;begin

{ Armazena os primeiros 3 caracteres em uma variável }

text1 := copy( dbedit1.Text,1,3);

{ Armazena os últimos três caracteres em outra variável , se o conteúdo da variável,usando a função, for menor que 3 significa que a pessoa não digitou 3 números, sendo inválido.}

text2 := copy( dbedit1.text,4,3); if length(apenasnumero(text2)) < 3 then showmessage(‘números inválidos’);end; {O objetivo dessa função é pegar somente números de uma string} Function ApenasNumero(str:string):string;var str2: string; i: integer;begin for i := Length(str) downTo 1 do if (str[I] in [‘0’..’9’]) then str2 := Copy(str, I, 1) + str2; Result:=str2;end;

Dúvida enviada por Marcelo Nogueira, Onda Verde – SP.

Pergunta: Gostaria de uma instrução SQL para retornar a diferença de dois campos do tipo Timestamp? Gostaria que me retornasse em HH:MM.

Resposta: Deverá montar uma select com o auxílio de uma UDF do Firebird chamada udf_MinutesBetween .

Abaixo a declaração da UDF:

perguntas & respostas

26

declare external function udf_MinutesBe-tweentimestamp, timestampreturns numeric(18,0) by valueentry_point ‘udf_MinutesBetween’ module_name ‘tbudf’;

Veja a instrução SQL:

SELECT data, current_timestamp, (udf_minutesbetween(current_timestamp,data)/60) || ‘:’ ||cast(((cast(24*(current_time-stamp - data) as numeric(15,3)) - udf_minutesbetween(current_timestamp,data)/60)*60) as integer) as “Horas/Minutos”FROM tabela

Nesta instrução SQL foi calculado a diferença entre dois campos do tipo Timestamp e retornando em hh:mm. Foi utilizado uma UDF de uma biblioteca de terceiros chamada tbudf.

Para declaração e utilização de UDFs recomendo a leitura da seguinte matéria:

http://www.theclub.com.br/revista/trab0707.aspx

Dúvida enviada por Silvia Berezin, São Paulo – SP.

Pergunta: Gostaria de saber se os senhores sabem se há a possibilidade de gerar um relatório com o Fortes Report sem que o RLreport esteja ligado a uma tabela?

Resposta: Estive realizando alguns testes com o Fortes Report. Poderá trabalhar sim sem o vínculo com uma tabela (já que não deseja utilizar uma) , mas fique atento poderá utilizar todos os tipos de bandas, menos a do tipo btDetail , pois esta necessita ter vínculo com algum campo de uma tabela.

Dúvida enviada por Israel, Três Pontas – MG.

Pergunta: Gostaria de saber como faço para adicionar uma string numa Stored Procedure?

Exemplo: Select da procedure:

SELECT CODIGO,DESCRICAO FROM TABELAWHERE TIPO = ‘T’ /* Aqui quero comparar o TIPO com */ /* uma variável de entrada onde */ /* pas-sarei o conteúdo “T”. Como */ /* faço neste caso? */INTO :VCOD,:VDES;

Resposta: Deverá criar um parâmetro de entrada e Fazer um For.. Select (laço), veja abaixo como deverá ficar o comando SQL para poder criar esta Stored Procedure!

CREATE PROCEDURE CONSULTAR( wnome varchar(60))returns ( vcod integer, vdes varcahar(60)asBegin For Select codigo, descricao From TABELA Where TIPO like :wnome Into :vcod, :vdes do Suspend;END

Dúvida enviada por Engenho Consultoria em Sistemas, São Paulo – SP.

Pergunta: Tenho como criar relatórios via código para impressora ma-tricial, com preview, escolher impressora na rede,com recursos do próprio Delphi, sem necessidade de ferramentas de terceiros ?

Resposta: Sim é possível, possuímos uma matéria a respeito deste assunto que deverá ajudá-lo, veja a seguinte matéria: http://www.theclub.com.br/revista/writ0104.aspx

Dúvida enviada por Paulo Roberto Ferreira de Brito, Anápolis – GO.

Pergunta: Gostaria de inserir fórmulas, alterar a cor da célula e o tipo da fonte no Excel, é possível?

Resposta: Sim, veja o código abaixo comentado:

perguntas & respostas

27

procedure TForm1.BitBtn1Click(Sender: TObject);var XLApp: Variant;Begin

XLApp := ComObj.CreateOleObject(‘excel.application’); XlApp.visible:=true; XlApp.WorkBooks.Open(ExtractFilePath(Application.ExeName) + ‘Exemplo.xls’); XlApp.WorkBooks[1].Sheets[1].Cells[2,1]:=’Teste1’; XlApp.WorkBooks[1].Sheets[1].Cells[2,2]:=’Teste2’; XlApp.WorkBooks[1].Sheets[1].Cells[2,3]:=’Teste3’;

{Inserindo Fórmulas no Excel} XlAPP.CELLS[4,1]:=’=C3-A3’; XlAPP.CELLS[4,2]:=’=B3+D3’; {Cor da célula} XLAPP.workbooks[1].sheets[1].cells[2,1].interior.color := $00ffcf9c; {Tipo da fonte} XLAPP.workbooks[1].sheets[1].cells[2,1].font.name := ‘Verdana’;end;

Dúvida enviada por Drake Indústria a Comércio LTDA.

Pergunta: Como fazer para que um OpenDialog exiba os arquivos no modo de exibição “Detalhes”, ou seja, como fazer para que eu possa escol-her o modo de exibição a ser mostrado, como (Miniaturas, Lado a Lado, Detalhes, etc).

Outra coisa, não quero que este modo de visualização fique fixo para todos os outros OpenDialogs que forem executados (inclusive de outras aplicações), quero que esta opção funcione apenas para o OpenDialog que eu fizer o devido tratamento.

Resposta: Veja abaixo o comando necessário para poder fazer isto.

{Declare um tipo}type TFileViewStyle = (fvsIcons, fvsList,

fvsDetails, fvsThumbnails, fvsTiles);var Form1: TForm1; implementation {$R *.dfm}

{Função utilizada}function SetFileDialogViewStyle(Handle: THandle; ViewStyle: TFileViewStyle): Boolean;const CommandIDs: array[TFileViewStyle] of Word = ($7029, $702B, $702C, $702D, $702E);var NotifyWnd: THandle;begin Result := False; NotifyWnd := FindWindowEx(GetParent(Handle), 0, ‘SHELLDLL_DefView’, nil); if NotifyWnd <> 0 then begin SendMessage(NotifyWnd, WM_COMMAND, CommandIDs[ViewStyle], 0); Result := True; end;end;

{Exemplo}procedure TForm1.BtnExecutarClick(Sender: TObject);begin OpenDialog1.Tag := 0; OpenDialog1.Execute;end; procedure TForm1.OpenDialog1FolderChange(Sender: TObject);begin if OpenDialog1.Tag = 0 then begin SetFileDialogViewStyle(OpenDialog1.Handle, fvsDetails) end;end;

Dúvida enviada por Afonso Celso de Paula Oliveira, Fartura – SP.

perguntas e respostas

28

Pergunta: Gostaria de implementar em meu sistema uma instrução SQL que me devolvesse a diferença entre duas datas retornando em Dias, Meses e Anos, é possível fazer isto no Firebird?

Resposta: Poderá implementar isto pelo Firebird com a ajuda de UDFs de terceiros, veja abaixo como ficaria:

SELECT (CAST(DATAFIM as DATE) - CAST(DATAINI AS DATE))/365 AS ANOS, udf_trunc(((udf_daySPAN(DATAFIM,DATAINI)/365) - (CAST(DATAFIM as DATE) - CAST(DATAINI AS DATE))/365)*12) AS MESES, udf_trunc((((udf_daySPAN(DATAFIM,DATAINI)/365) - (CAST(DATAFIM as DATE) - CAST(DATAINI AS DATE))/365)*12 - udf_trunc(((udf_daySPAN(DATAFIM,DATAINI)/365) - (CAST(DATAFIM as DATE) - CAST(DATAINI AS DATE))/365)*12))*30) AS DIASFROM TABELA

Observação: estou utilizando UDF de terceiro, chamada tbudf, vide matéria para detalhes na utilização destas UDFs –

http://www.theclub.com.br/revista/trab0707.aspx

Dúvida enviada por Maicon, Laurentino – SC.

Pergunta: Tenho 100 Panels em um Formulário, como fazer para exibir o Caption do Panel clicando nele sem precisar inserir o código “ShowMessage(Panel1.Caption);” em cada Panel?

Ou seja, preciso identificar o objeto clicado em tempo de execução, pas-sando o próprio objeto no evento OnClick do Panel. Tem como fazer isto?

Resposta: Deverá utilizar a variável Sender.

Segue abaixo o código genérico que deverá ser colocado no evento Onclick de todos os Panels.

ShowMessage((sender as Tpanel).Name);

Dúvida enviada por Juliana, São Paulo – SP.

Pergunta: Como posso fazer a barra da forma minimizada piscar alguns segundos?

Resposta: Poderá utilizar uma API do Windows chamada FlashWindow. Uma sugestão seria de colocá-la em um componente Timer e verificar se a aplicação foi minimizada. Segue abaixo o código:

procedure TForm1.Timer1Timer(Sender: TO-bject);begin if (GetForegroundWindow <> Form1.Handle) then FlashWindow(Application.Handle, True);end;

Dúvida enviada por Auto Peças Meridional, Porto Alegre – RS.

Pergunta: Como faço para gravar um campo com valor “null” no Delphi .Net? Estou utilizando parâmetros do Firebidsql. Exemplo: fbcInsert.Parameters[‘@pj_dnascto’].Value := txtDnascto.

Text;

Resposta: Utilize o seguinte código para inserir nulos

Bdpcom.Parameters[0].value := Convert.DBNull;

Exemplo de utilização:

procedure TWinForm.Button1_Click(sender: System.Object; e: System.EventArgs); var Bdpcom : FbCommand;begin FbConnection1.Open; Bdpcom := FbCommand.Create(‘UPDATE TA-BELA SET DATA = @Parm’, FbConnection1); Bdpcom.CommandType := CommandType.Text; Bdpcom.Parameters.Clear; Bdpcom.Parameters.Add(‘@Parm’, FbDb-Type.Date); Bdpcom.Parameters[0].value := Convert.DBNull; Bdpcom.ExecuteNonQuery; FbConnection1.Close;end;

perguntas e repostas

29

Dúvida enviada por Nilton Charles Rabelo Feitosa, Aracaju – SE.

Pergunta: Gostaria de saber se há a possibilidade de gravar uma Data em branco via instrução SQL? Estou utilizando o conjunto de componentes ADO.

Resposta: Sim, é possível, segue abaixo um exemplo de como deve ser feito.

procedure TForm1.Button1Click(Sender: TObject);begin with ADOQuery1, SQL do begin Add(‘INSERT INTO EMPLOYEE(EMPNO, LASTNAME, FIRSTNAME, PHONEEXT, HIREDATE, SALARY) VALUES’); Add(‘(:EMPNO, :LASTNAME, :FIRSTNAME, :PHONEEXT, :HIREDATE, :SALARY)’); Parameters.ParamByName(‘EMPNO’).Value := 146; Parameters.ParamByName(‘LASTNAME’).Value := ‘Ferreira’; Parameters.ParamByName(‘FIRSTNAME’).Value := ‘Alessandro’; if edt_Telefone.Text = ‘’ then Parameters.ParamByName(‘PHONEEXT’).Value := Null; else Parameters.ParamByName(‘PHONEEXT’).Value := edt_Telefone.Text; if medt_Data.Text = ‘’ then Parameters.ParamByName(‘HIREDATE’).Value := Null; else Parameters.ParamByName(‘HIREDATE’).Value := medt_Data.Text;

Parameters.ParamByName(‘SALARY’).Value := 5000;

ExecSQL; end;end;

Dúvida enviada por Luiz Roberto A. Fernandes, São Paulo – SP.

Pergunta: Existe alguma forma de saber quando o dia da semana é um domingo?

Resposta: Existe a possibilidade, veja abaixo o exemplo que faz o uso da função DayOfWeek. Caso o retorno seja igual a 1 será domingo.

Observe: No exemplo abaixo foi utilizado um componente DateTim-

erPicker, mas poderá utilizar facilmente um campo do tipo data.

procedure TForm1.Button1Click(Sender: TObject);begin if (DayOfWeek(datetimepicker1.Date) = 1) then ShowMessage(‘É Domingo!’) else ShowMessage(‘Não é Domingo!’);end;

Dúvida enviada por Sandro, Recife – PE.

Pergunta: Como saber se o Delphi está aberto? Desejo colocar uma opção na aplicação para saber se está em modo de programação ou não.

Resposta: É necessário montar uma função para verificar se o Delphi está rodando e colocá-la no evento Oncreate do Formulário principal, veja abaixo:

Function JanelaExiste(Classe,Janela:String) :Boolean;var PClasse,PJanela : array[0..79] of char;begin if Classe = ‘’ then PClasse[0] := #0 else StrPCopy(PClasse,Classe); if Janela = ‘’ then PJanela[0] := #0 else StrPCopy(PJanela,Janela); if FindWindow(PClasse,PJAnela) <> 0 then result := true else Result := false;end;

Function DelphiCarregado : Boolean;begin Result := False;

perguntas e respostas

30

if JanelaExiste(‘TPropertyInspector’,’Object Inspector’) then result := Trueend;

{Através de um Botão chamaremos a função acima}procedure TForm1.FormCreate(Sender: TOb-ject);begin if DelphiCarregado then showmessage(‘Delphi está ativo!’) else begin Showmessage(‘Delphi não está Ativo!’); end;

end;

Dúvida enviada por GRV Software, Vinhedo – SP.

Pergunta: Tenho um componente Treeview e gostaria de retornar a Hierarquia de um determinado Nó, isto é possível?

Resposta: Sim, basta montar uma rotina simples para verificar se este nó possui “pais”, veja abaixo:

procedure TForm1.BitBtn1Click(Sender: TObject);var NoRaiz:TTreeNode;begin if TreeView1.Selected = nil then Exit; NoRaiz := TreeView1.Selected; While NoRaiz.Parent <> nil do begin NoRaiz := NoRaiz.Parent; caption := NoRaiz.Text +’ ‘+ cap-tion; end;end;

Neste exemplo estamos jogando o resultado na propriedade Caption do Formulário.

Dúvida enviada por Thaise, Santo André – SP.

Pergunta: Estou montando um gráfico de funcionários limitando a im-pressão até no máximo de 10 pessoas. Existe alguma forma de pegar apenas o primeiro nome de cada funcionário como mostra o exemplo abaixo?

FUNCIONÁRIOS RESULTADO DESEJADO-------------------------------------------- -----------------------SANDRO RIBEIRO DA SILVA - SANDROROGERIO BARROS DE MORAIS - ROGÉRIOTATIANE PEIXOTO DE SOUZ - TATIANEFRANCISCO OLIVEIRA DA CUNHA - FRANCISCO

Resposta: Uma das formas para resolver este problema seria utilizar uma função para retirar os sobrenomes das pessoas, veja a função abaixo:

function RetiraSobrenome(str: string): String;var strtotal: string; i: integer;begin for i:=1 to length(str) do begin strtotal := strtotal + (copy(str,i,1)); if ((copy(str,i,1)) = ‘ ‘) then begin break; end; end; result := strtotal;end;

Dúvida enviada por Softline Informática Ltda, Recife – PE.