Estava faltando descomplicar...
O xHarbour (Extended Harbour) é um fork do Projeto Harbour. Nasceu de uma dissidência entre os desenvolvedores que de um lado queriam manter a linguagem original e de outro queriam adicionar parâmetros à mais nas funções, deixando-as melhores economizando linhas de código e a vida do programador. Qual o problema disso? Apesar de continuar 100% compatível com o Clipper, a recíproca não era verdadeira e sairia do padrão da linguagem xBase. Por exemplo, um programa desenvolvido em Clipper ou Harbour vai compilar com o xHarbour, mas um programa desenvolvido em xHarbour pode dar erros se for compilado com o Harbour.
Eu acho o xHarbour melhor, mas o Harbour é mais consistente entre as versões e manterá a compatibilidade com outros compiladores xBase.
Estava cansado de encontrar tanta coisa dizendo nada sobre o Harbour... Agora eu consegui compilar um .EXE e até uma .LIB, agora é a sua vez ! AVANÇA BRASIL!
Observei que há várias LIBs Gráficas para o xHarbour!!! FWH, MiniGui, What32, Whoo, C4W e HWGUI aparecem na criação do arquivo .BC. São aplicativos de 32bits reais do Windows !...
Observei, ainda, que existe algums Gerenciadores de Banco de Dados, tipo o caríssimo ADS (Advantage Data Server), assim como o Mediator, Apollo etc... que também aparecem na criação do arquivo .BC. Isto, é... agora, tudo é GRATUITO ?!... Além desses, também há suporte para o Oracle, SQL, PostGres etc.
Compila tanto para Windows, como para Linux e OS/2 !...
Em nome de todos os clippeiros, agradeço a ajuda de Taibnis S. Vieira da empresa Futura Tecnologia em Brasília por revelar o caminho das pedras... Agradeço a todos os outros que também colaboraram para manter esta página o mais operacional possível !
Se você quer saber mais sobre a história do Projeto Harbour, visite: https://pt.wikipedia.org/wiki/Harbour_(compilador)
A diferença aqui neste novo site é que o usuário registrado poderá adicionar suas informações e ver tudo publicado automaticamente, pois para o usuário registrado aparecerá o link "Nova subpágina" e "Comentar" no rodapé desta página onde o mesmo poderá começar a interagir. Participe! Inclua suas folhas neste livro, anexe exemplos, programas etc.
Download do xHarbour - Aprenda a fazer o download do compilador xHarbour, manuais etc. Confira todos os links.
Estava faltando descomplicar...
Os links abaixo foram retirados do ar. Não sei por que razão eles agora só colocaram versão com o compilador C Embarcadero pago. Por que não poderiam usar a versão Embarcadero 7.20 Free?
xHarbour Binaries 1.2.3 Rev. 10264 for BCC 5.8.2 C:\ ( 4.44Mb) Binaries for Windows BCC 5.8.2
http://www.xharbour.org > Download Binaries >Windows > xHarbour Binaries for Borland C++ 5.8.2
Enfim, eu tenho e estou disponibilizando a última versão do xHarbour com o BCC58 no fim desta página para download. Depois passe para a página de instalação para terminar a configuração.
O xHarbour transforma a linguagem xBase em C e o compilador C em um executável.
Este arquivo está disponível para baixar no final desta página. No site oficial eles deixaram apenas a versão com o BCC 7.40 que não é gratuito.
Borland C++ Compiler 5.8.2 c:\bcc58 ( 8.7Mb)
http://www.xharbour.org >Download > Required Tools
BCC é o compilador C do xHarbour. O BCC58 é necessário para compilar a última versão do xHarbour (v1.2.3)
Estamos deixando disponível também o xHarbour v1.2.1 e o BCC55 no final desta página para download.
http://groups.google.com/group/comp.lang.xharbour/topics
news://news.xHarbour.org/xHarbour
É obrigatório usar o inglês nesses canais de suporte. Se tiver uma palavrinha em português eles rejeitam a sua mensagem.
Compactador de executável (do seu aplicativo gerado pelo xharbour, deixa ele com tamanho menor).
-Coloque o UPX.EXE no C:\BCC55\BIN ou C:\BCC58\BIN
Documentação completa do xHarbour (
4.268Kb) OPCIONAL
Norton Guide do xHarbour (antigo)c:\ng (
173Kb) OPCIONAL
TODOS OS ARQUIVOS ACIMA SÃO FREEWARE, GRATUITOS!
DICAS DE INSTALAÇÃO DO xHARBOUR
Há 1 arquivo para observar na instalação do xHarbour e 3 arquivos na instalação do BCC.
1. Descompacte o xHarbour (Binários e LIBs) no diretório raíz do C:\ e já será criado a pasta C:\XHARBOUR com os subdiretórios.
Observe o arquivo harbour.cfg que está em c:\xharbour\bin
CC=BCC32 CFLAGS= -c -D__EXPORT__ -IC:\XHARBOUR\include -d -LC:\XHARBOUR\lib VERBOSE=YES DELTMP=YES
Observe que há 2 caminhos aí para as pastas INCLUDE e LIB. Confirme se apontam para a localização correta, caso tenha instalado em outra unidade que não a C: então mude aí.
2. Instale o Borland C++ no diretório C:\BCC55 (xHarbour v1.2.1) ou C:\BCC58 (xHarbour v1.2.3)
3. Descompacte o arquivo harbour_cfg.zip dentro do subdiretório C:\BCC55\bin ou C:\BCC58
Enfim, na pasta BIN do Borland C++ você precisa observar se os caminhos da instalação estão corretos nos arquivos BCC32.CFG, ILINK.CFG e TLINK.CFG.
O arquivo BCC32.CFG contém:
-I"C:\BCC55\include" -L"C:\BCC55\lib;C:\BCC55\lib\psdk"
O arquivo ILINK.CFG contém:
-L"C:\BCC55\lib;C:\BCC55\lib\psdk"
O arquivo TLINK32.CFG contém:
/L"C:\BCC55\lib"
Veja que dentro deles estão o caminho de instalação do BCC55 e do xHarbour. O "-I" para arquivos "include" e "-L" para "lib". Se estes caminhos não estiverem corretos, não funcionará! Por isso que tem que instalar nas pastas recomendadas.
Crie um arquivo de lote com as configurações de variáveis de ambiente (amb.bat):
SET PATH=%PATH%;C:\XHARBOUR\BIN;C:\BCC55\BIN SET HB_DIR=C:\XHARBOUR SET HB_PATH=C:\XHARBOUR SET INCLUDE=%INCLUDE%;C:\XHARBOUR\INCLUDE;C:\BCC55\INCLUDE SET LIB=%LIB%;C:\XHARBOUR\LIB;C:\BCC55\LIB
Outra forma de incluir variáveis de ambiente no Windows 2000/XP/NT (principalmente se o Windows não puxou estas variáveis de ambiente do AUTOEXEC.BAT), é seguir os seguintes passos:
INICIAR PAINEL DE CONTROLE
SISTEMA
AVANÇADO
VARIÁVEIS DE AMBIENTE
Clique no menu "Iniciar", depois em "Painel de Controle". Escolha então "Sistema".
Na janela que abrir, clique na aba "Avançado" e depois no botão "Variáveis de Ambiente".
Na próxima tela, clique no botão "Nova" do quadro "Variáveis do sistema".
Coloque o nome da variável no primeiro campo e o valor no segundo.
ATENÇÃO! Não altere os diretórios de instalação sugeridos aqui para não complicar sua instalação!
Para testar se conseguiu configurar as variáveis de ambiente, use o comando SET no prompt do DOS.
Talvez você precise dar uma pausa para enxergar tudo, então use: SET |MORE ou então mande a saída do comando para um arquivo e abra com o Edit ou Notepad, use o parâmetro ">nome do arquivo" com o comando, assim: SET >AMBI.TXT, depois é só abrir o arquivo criado AMBI.TXT e ver todas as variáveis de ambiente criadas. Talvez você queira mandar esse arquivo para um amigo ou postá-la num fórum para mostrar como está seu ambiente e pedir mais ajuda.
Caso você queira deixar o Clipper e o xHarbour rodando quando quiser, observe que as definições do Clipper vem antes do xHarbour, caso contrário não funcionará com ambos.
Exemplo:
SET INCLUDE=C:\COMPILER\CLIPPER5\INCLUDE;C:\Bcc55\include;C:\xHarbour\include SET LIB=C:\COMPILER\CLIPPER5\LIB;C:\COMPILER\BLINKER\LIB;C:\Bcc55\lib;C:\xHarbour\lib SET PATH=%PATH%;C:\COMPILER\CLIPPER5\BIN;C:\COMPILER\BLINKER;C:\XHARBOUR\BIN;C:\BCC55\BIN
DICAS DE FUNCIONAMENTO DO xHARBOUR
Estava faltando descomplicar...
Como criar um EXEcutável:
É obrigatório a existência de um FUNCTION MAIN() dentro do seu sistema, isso você já sabe, mas no xHarbour, mesmo que você esteje compilando um único PRG, será necessário começar com FUNCTION MAIN() também!
O programa HBMAKE é uma ferramenta que cria um arquivo com a extensão ".BC" que equivale aos arquivos "*.RMK" e "*.LNK", facilitando a sua vida. Os principais parâmetros são:
/EX | Cria o arquivo .BC destinado a constituir um EXE. |
/ELX | Cria o arquivo .BC destinado a constituir uma LIB. |
/F | Força a recompilação da lista de programas que compõem o sistema. |
Se não for informado nenhum parâmetro, vai compilar só os programas listados no arquivo .BC que foram modificados desde a última compilação.
Para criar os programas você pode usar o Notepad++ que é super leve e tem a função highlight para visualizar melhor o código. Você vai precisar importar a linguagem Harbour que disponibilizo abaixo para download porque o Notepad++ não tem ela nativa.
Depois disso, você tem que configurar o conjunto de caracteres que usamos em nossa língua portuguesa:
Notepad++: Formatar > Conjunto de caracteres > Europa Ocidental > OEM850
Primeira coisa que você tm que saber é que todo programa xHarbour tem que ter um Function Main() para indicar onde começar. Main() é um nome reservado. Equivale ao já conhecido INIT FUNCTION ou INIT PROCEDURE, porém no Clipper isso não era obrigatório.
Vamos compilar o clássico "hello world" no código a seguir.
Abra o Notepad++, ajuste o conjunto de caracteres e cole o programa a seguir nele:
function main() // Linha obrigatória. Define as primeiras linhas a serem executadas. ? "Hello World!"
Salve-o como "OI.prg".
Para criar o oi.exe você vai primeiro criar o arquivo da compilação, o oi.bc:
HBMAKE OI.BC /EX
Depois você vai compilar assim:
HBMAKE OI.BC
O sistema já vai compilar certinho com os acentos na lingua portuguesa.
Veja o passo-a-passo a seguir:
Os comandos para criação de um executável são:
HBMAKE OI.BC
Para criar um arquivo de compilação de um EXE (aplicativo):
HBMAKE nome.bc /EX
...e para compilar o aplicativo:
HBMAKE nome.bc
Irá compilar somente os PRGs alterados desde a última compilação.
Para forçar a recompilação de todos os PRGs:
HBMAKE nome.bc /F
Este parâmetro /F também regera o arquivo HARBOUR.CFG, não há problema nisso.
Onde "nome.bc" é o nome do script que você vai criar, ponha o nome que quiser, mas deixe a extensão .BC. O arquivo .BC só precisa ser criado uma única vez, a não ser que você deseje incluir novos programas no seu sistema.
No primeiro passo, é criado um arquivo com o nome nome.bc (pode ser qualquer nome, mas a extensão é bc). Este arquivo é um tipo de mescla de RMK e LNK do Clipper. É um roteiro (ou script, como preferir) de compilação.
Nesta primeira chamada é aberta uma janela do DOS com algumas perguntas sobre qual o sistema operacional, compilador, LIB gráfica, RDDs etc.
Vamos demonstrar de forma ilustrada os passos básicos para a compilação de um programa comum (sem Libs gráficas ou RDDs) para ser executado na plataforma Windows e compilado usando o Borland C++ que você baixou deste site.
HBMAKE oi.bc /EX
A tela que se apresenta é a seguinte:
Basta você ir teclando <Enter> até "[X]Comprimir App"*, marque-o para produzir executáveis menores e até o "Nome Executável", onde você vai por o nome do arquivo .EXE que será gerado. Neste exemplo acima, será geradoOI.EXE.
*Para comprimir o executável, você precisará baixar o UPX.
Após por o Nome do Executável, abrirá outros campos como visto a seguir:
Vá teclando <Enter> até o "[X] Compila apenas o módulo /m", marque-o e continue teclando <Enter> até aparecer uma pequena janela com uma lista de todos os arquivos .PRG do diretório corrente, como na tela seguir:
Nesta janela que se abre, você vai selecionar, teclando com a barra de espaços do seu teclado, todos os arquivos .PRG que vão fazer parte do seu sistema e depois deverá teclar <Enter> para finalizar.
Esta janela irá fechar e aparecerá outras opções, mas vá teclando <Enter> até a pergunta "Compilar app?", no canto inferior esquerdo da tela, veja a tela seguinte:
Responda com "S" para compilar o seu sistema agora ou "N" para compilar depois com HBMAKE OI.BC no prompt do MS-DOS.
Voilà! Está pronto o seu roteiro (ou script, como preferir) para compilar o arquivo EXEcutável. Observe que este processo todo serve apenas para criar o arquivo com a extensão .BC, que nunca mais necessitará ser criado de novo ao menos que você queira incluir um novo arquivo .PRG no seu sistema posteriormente.
No segundo passo é feita a criação do executável.
HBMAKE oi.bc
ou
HBMAKE oi.bc /F
Caso seu programa não apresente erros, a tela que se apresenta é a seguinte:
Caso dê algum erro, abra o arquivo com a extensão .OUT ou .LOG para entender o que aconteceu.
Para criar uma LIB:
HBMAKE nomedalib.bc /ELX HBMAKE nomedalib.bc
O programa da LIB deve começar com a criação de uma função qualquer, tipo FUNCTION TESTE(). Não ponha o nome de "MAIN" porque esta função FUNCTION MAIN() é reservada para chamar o programa principal do sistema, ou seja, o programa do sistema que executa primeiro, aquele que prepara o ambiente, a tela e o menu do sistema, por exemplo.
A primeira chamada de HBMAKE cria um arquivo com a extensão .BC, que já falamos anteriormente. Marque apenas a opção: [X] Compila apenas o módulo /m
A segunda chamada de HBMAKE cria a LIB propriamente dita.
Os problemas de programação só aparecem na segunda chamada e podem ser analisados abrindo o arquivo com a extensão .OUT ou .LOG.
Exemplo de primeiras linhas de um sistema em xHarbour:
// SETs SET SCOREBOARD OFF SET DATE BRITISH SET MESSAGE TO 24 SET DELETED ON SET EPOCH TO 1980 SETMODE(25,80) SET OPTIMIZE ON // otimização de filtros (SET FILTER TO) SETMOUSE(.t.) // Mostra o cursor do mouse na tela SET EVENTMASK TO 255 // INKEY_ALL = MOUSE NOS GETs SET TIME FORMAT TO "hh:mm" SETCOLOR(cCOR) SET CONFIRM ON // DEFINIR IDIOMA PORTUGUÊS // REQUEST HB_LANG_PT REQUEST HB_CODEPAGE_PT850 HB_LangSelect("PT") HB_SetCodePage("PT850") // DEFINIR TIPO DE BANCO DE DADOS: DBFCDX Nativo REQUEST DBFCDX REQUEST DBFFPT ANNOUNCE FPTCDX RDDSETDEFAULT("DBFCDX") RDDREGISTER( "DBFCDX", 1 ) // RDT_FULL SET AUTOPEN OFF
Observe que o "modo de edição rápida" das propriedades da janela do MS-DOS tem que estar desativada para o mouse funcionar, tipo:
Estava faltando descomplicar...
Páginas oficiais:
Projeto Harbour - Versão Freeware/Open Source (Compilador)
http://www.harbour-project.org
Borland C++ Compiler Freeware (Linkador)
http://www.borland.com/products/downloads/download_cbuilder.html
Projeto Harbour - Versão Comercial (Compilador+Linkador)
Grupo de Notícias (Newsgroup) - Obtenha ajuda aqui (Use MS Outlook)
news://news.xharbour.org/xHarbour.Spanish.Portuguese
news://news.xharbour.org/xHarbour
Outros sites sobre o Projeto Harbour etc.
How to Projeto Harbour -Outro site com mais dicas de download, instalação e funcionamento.
http://www.susviela.hpg.ig.com.br/hb/ -Dicas para Harbour e curso de Harbour MiniGUI (HMG -Lib gráfica p/ o Harbour)
CoreFTP freeware -Melhor FTP grátis. Ao invés de baixar arquivos um a um, selecione as pastas e automatize o download. Útil p/ baixar o DJGPP.
Turbo Assembler 5 Freeware (completo)
tasm5_1.zip, tasm5_2.zip e tasm5_3.zip.
BISON Freeware
http://www.gnu.org/software/bison/
DJGPP Freeware
Libs Gráficas
HwGUI (freeware/Open source) -É multi-plataforma!
Quem quiser migrar para Windows gratuitamente, use esta LIB.
Visual xHarbour (Software/Comercial)
Linguagem Visual interativa para Windows e programável para Clipper (xBase).
Quem disse que o navio iria afundar e você iria morrer na praia?! Quem programa em Clipper pode ancorar o navio neste porto!!!
Quem abandonou o navio (Clipper) e está no Delphi ou VB, pode voltar ao porto (Harbour) e entrar no navio (Clipper) de novo!!!
(A linguagem Clipper é simbolizada por um navio e "Harbour" quer dizer "porto")
FiveWin for Harbour (FWH) - FiveTech Software (Software/Comercial)
Visual Lib 2.3 (freeware) (
1429Kb)
A mesma Visual Lib do Clipper agora na versão compatível com o Harbour/xHarbour. Continua sendo uma LIB pseudo visual, fazendo o mesmo que antes. Para conseguir arquivos reais do Windows, use uma das outras LIBs acima.
MWVW (Software/Comercial)
A MWVW.LIB tem como objetivo principal, facilitar na conversão e utilização moderada de recursos gráficos visuais, usando parcialmente o que esta presente na GTWVW.LIB (OpenSource criado por Budyanto Dj).
É destinada para sistemas desenvolvidos em xHarbour modo texto na plataforma Windows (mas poderá usar em conjunto com outras libs gráficas).
Outras LIBs
SIBRAH - Sistema de Impressão BRAsileiro para Harbour (Software/Trial)
Para quem quiser imprimir em qualquer impressora sem precisar aprender muita coisa e aproveitar o melhor do xHarbour! Imprime gráficos, código de barras etc. Já estão embutidos a GDLIB e a FreeImage dentro desta LIB.
GDLIB (freeware) CVS: C:\XHARBOUR\CONTRIB\GD
LIB para imprimir em código de barras: EAN13, EAN8 e EAN128 A/B/C. Possui capacidade para desenhar etc.
-Coloque o arquivo bgd.dll no diretório indicado e chame "MAKE_B32.BAT".
*Caso dê erro, abra o arquivo "makefile.bc" e edite a linha "BCC_DIR=C:\XHARBOUR\BCC55".
FreeImage (freeware) CVS: C:\XHARBOUR\CONTRIB\FREEIMAGE
LIB para tratamento de imagens. Converte um tipo de imagem em outro etc.
-Coloque o arquivo freeimage.dll no diretório indicado e chame "MAKE_B32.BAT".
*Caso dê erro, abra o arquivo "makefile.bc" e edite a linha "BCC_DIR=C:\XHARBOUR\BCC55".
Estava faltando descomplicar...
Vide exemplo de minha autoria que baixa um arquivo da internet... talvez ficar milionário!
Para trabalhar com as funções HB_UNZIPFILE e HB_ZIPFILE você precisa linkar as LIBs: hbzip.lib; hbmzip.lib; zlib.lib.
Estamos anexando o programa para download no rodapé.
FUNCTION MAIN() *** definições iniciais ***------------------------------------------------- SETMODE(60,132) *** SETs SET SCOREBOARD OFF SET DATE BRITISH SET(36, 23) SET(37, .F.) SET DELETED ON SET EPOCH TO 1980 SETMODE(25,80) SET MESSAGE TO 24 SET OPTIMIZE ON SETMOUSE(.t.) SET(39,159) // MOUSE NOS GETs SET TIME FORMAT TO "hh:mm" SET CENTURY ON SET CONFIRM ON REQUEST HB_LANG_PT HB_LangSelect("PT") HB_SetCodePage("PT850") #IFDEF __GTWVW__ wvw_setcodepage(,255) #ENDIF *** DEFINIR TIPO DE BANCO DE DADOS: DBFCDX Nativo *** REQUEST DBFCDX REQUEST DBFFPT ANNOUNCE FPTCDX RDDSETDEFAULT("DBFCDX") RDDREGISTER( "DBFCDX", 1 ) // RDT_FULL SET AUTOPEN OFF *** DEFINIR IDIOMA PORTUGUÊS *** REQUEST HB_CODEPAGE_PT850 &&& PARA INDEXAR CAMPOS ACENTUADOS HB_SETCODEPAGE("PT850") &&& PARA INDEXAR CAMPOS ACENTUADOS *** LIMPA A TELA E MOSTRA PRIMEIRAS INFORMAÇÕES CLS ? "*** MEGASENA ***" ? "SORTEIOS SÃO REALIZADOS ÀS QUARTAS E SÁBADOS" ? dBANCO := FILEDATE("SENA.DBF") // DATA DE GERAÇÃO DO ARQUIVO SENA.DBF ? "HOJE: "+DTOC(DATE()) + " - ÚLTIMA CARGA: "+DTOC(dBANCO) ? IF EMPTY(dBANCO) .OR. DATE() # dBANCO IF (ALERT("ATUALIZA ARQUIVOS AGORA?", {"SIM", "NÃO"}))=1 *** BAIXA ARQUIVO COM OS RESULTADOS DA INTERNET AUTOMATICAMENTE cURL := "http://www1.caixa.gov.br/loterias/_arquivos/loterias/D_megase.zip" oHTTP := TIpClientHttp():new( cURL ) cARQ := "D_MEGA.HTM" // ARQUIVO COM OS RESULTADOS DOS SORTEIOS cZIP := "D_megase.zip" IF oHTTP:OPEN() ? "BAIXANDO ARQUIVO COM OS RESULTADOS DA INTERNET..." ? cURL ? cBIN := oHttp:readAll() // BAIXA ARQUIVO E GRAVA EM cBIN oHTTP:CLOSE() Memowrit( cZIP, cBIN ) // CRIA ARQUIVO COM cBIN IF FILE(cZIP) ? cZIP, ALLTRIM(STR( HB_FSIZE(cZIP)/1024 ))+"Kb", FILEDATE(cZIP) ? "SUCESSO!" ? ENDIF ? "DESCOMPACTANDO O ARQUIVO '"+cARQ+"' DE 'D_megase.zip'" IF HB_UNZIPFILE(cZIP,,,,".\",cARQ) ? cARQ, ALLTRIM(STR( HB_FSIZE(cARQ)/1024 ))+"Kb", FILEDATE(cARQ) ? "SUCESSO!" ? ELSE ? "NÃO FOI POSSÍVEL DESCOMPACTAR O ARQUIVO '"+cARQ+"' AUTOMATICAMENTE" ? "DESCOMPACTE-O MANUALMENTE AQUI NESTA PASTA DO PROGRAMA" ? ENDIF ELSE ? "Erro de conexão:", oHttp:lastErrorMessage() ? "BAIXE O ARQUIVO "+cURL+ " MANUALMENTE DA INTERNET E DESCOMPACTE ELE NA PASTA DESTE PROGRAMA." ENDIF IF !FILE(cARQ) ? "NÃO É POSSÍVEL ATUALIZAR SEM O ARQUIVO '"+cARQ+"'." ? "ABORTANDO PROGRAMA..." QUIT ENDIF *** RECIPIENTE DO ARQUIVO IMPORTADO ? TIME()+" - CRIANDO BANCO DE DADOS RECIPIENTE DO ARQUIVO D_MEGA.HTM..." RUN ("DEL SENA.DBF") aDBF = {} aadd(aDBF, {"TAG", "C", 4, 0}) aadd(aDBF, {"DATA", "C", 10, 0}) // PEGAR DATA SORTEIO COMO MARCO INICIAL aadd(aDBF, {"RESTO", "C", 3000, 0}) dbcreate("SENA.DBF", aDBF) ? TIME()+" - RENOMEANDO O ARQUIVO D_MEGA.HTM P/ D_MEGA.TXT P/ IMPORTAÇÃO DAS INFORMAÇÕES..." IF FILE("D_MEGA.HTM") RUN ("DEL D_MEGA.TXT") RUN RENAME D_MEGA.HTM D_MEGA.TXT ELSEIF !FILE("D_MEGA.TXT") ? "ALERTA: FALTA BAIXAR ARQUIVO COM OS RESULTADOS DA MEGASENA" ? "ABORTANDO..." QUIT ENDIF ? TIME()+" - IMPORTANDO TODAS AS INFORMAÇÕES DO ARQUIVO D_MEGA.HTM PARA SENA.DBF..." USE SENA ALIAS SE EXCLUSIVE NEW APPEND FROM D_MEGA.TXT SDF ? TIME()+" - CRIANDO ARQUIVO SORTEIOS.DBF P/ ARMAZENAR SÓ AS DEZENAS JÁ SORTEADAS..." IF FILE("SORTEIOS.DBF") RUN ("DEL SORTEIOS.DBF") ENDIF aDBF = {} aadd(aDBF, {"DEZ1", "N", 2, 0}) aadd(aDBF, {"DEZ2", "N", 2, 0}) aadd(aDBF, {"DEZ3", "N", 2, 0}) aadd(aDBF, {"DEZ4", "N", 2, 0}) aadd(aDBF, {"DEZ5", "N", 2, 0}) aadd(aDBF, {"DEZ6", "N", 2, 0}) dbcreate("SORTEIOS.DBF", aDBF) ? TIME()+" - LENDO O ARQUIVO SENA.DBF PARA GRAVAR AS DEZENAS SORTEADAS EM SORTEIOS.DBF..." USE SORTEIOS ALIAS DEZ EXCLUSIVE NEW SELECT SE // SENA.DBF SE->(DBGOTOP()) // POSICIONA NO 1° REGISTRO DO WHILE !SE->(EOF()) // FAÇA ENQUANTO NÃO É FIM DO ARQUIVO dSORTEIO := CTOD(SE->DATA) // TRANSFORMA CAMPO CARACTER PARA DATA, SE FOR DATA. IF !EMPTY(dSORTEIO) // SE TRANSFORMOU, O CAMPO É DATA. NO CASO, A DATA DO SORTEIO. // AS 6 LINHAS SEGUINTES SÃO AS DEZENAS SORTEADAS. SE->(DBSKIP()) // PULA P/ PROXIMA LINHA DEZ->(DBAPPEND()) // INSERE REGISTRO EM BRANCO // AS 6 LINHAS SEGUINTES SÃO AS DEZENAS SORTEADAS DEZ->DEZ1 := VAL( LEFT(SE->DATA,2) ) SE->(DBSKIP()) // PULA P/ PROXIMA LINHA DEZ->DEZ2 := VAL( LEFT(SE->DATA,2) ) SE->(DBSKIP()) DEZ->DEZ3 := VAL( LEFT(SE->DATA,2) ) SE->(DBSKIP()) DEZ->DEZ4 := VAL( LEFT(SE->DATA,2) ) SE->(DBSKIP()) DEZ->DEZ5 := VAL( LEFT(SE->DATA,2) ) SE->(DBSKIP()) DEZ->DEZ6 := VAL( LEFT(SE->DATA,2) ) ENDIF SE->(DBSKIP()) ENDDO SE->(DBCOMMIT()) // DESPEJA CACHE NO DISCO, FORÇA GRAVAÇÃO. ? TIME()+" - CRIANDO ARQUIVO RANKING.DBF P/ RANKING DAS DEZENAS MAIS SORTEADAS..." RUN ("DEL RANKING.DBF") RUN ("DEL RANKING.CDX") // AS 6 DEZENAS NEM SEMPRE CONTÉM OS NÚMEROS MAIS SORTEADOS // POR ISSO FAREMOS UM RANKING PARA CADA UMA DAS 6 DEZENAS // ASSIM AUMENTAMOS A CHANCE aDBF = {} aadd(aDBF, {"DEZ1", "N", 2, 0}) // DEZENA aadd(aDBF, {"RPT1", "N", 5, 0}) // VEZES QUE ELA SE REPETE aadd(aDBF, {"RNK1", "N", 2, 0}) // RANKING: POSIÇÃO EM QUE OCUPA ENTRE AS MAIS SORTEADAS aadd(aDBF, {"DEZ2", "N", 2, 0}) aadd(aDBF, {"RPT2", "N", 5, 0}) aadd(aDBF, {"RNK2", "N", 2, 0}) aadd(aDBF, {"DEZ3", "N", 2, 0}) aadd(aDBF, {"RPT3", "N", 5, 0}) aadd(aDBF, {"RNK3", "N", 2, 0}) aadd(aDBF, {"DEZ4", "N", 2, 0}) aadd(aDBF, {"RPT4", "N", 5, 0}) aadd(aDBF, {"RNK4", "N", 2, 0}) aadd(aDBF, {"DEZ5", "N", 2, 0}) aadd(aDBF, {"RPT5", "N", 5, 0}) aadd(aDBF, {"RNK5", "N", 2, 0}) aadd(aDBF, {"DEZ6", "N", 2, 0}) aadd(aDBF, {"RPT6", "N", 5, 0}) aadd(aDBF, {"RNK6", "N", 2, 0}) dbcreate("RANKING.DBF", aDBF) USE RANKING ALIAS RNK EXCLUSIVE NEW // CRIANDO ARQUIVO DE ÍNDICES INDEX ON STRZERO(DEZ1,2) TAG DEZ1 TO RANKING INDEX ON DESCEND( STRZERO(RPT1,2) ) TAG RPT1 TO RANKING INDEX ON STRZERO(RNK1,2) TAG RNK1 TO RANKING INDEX ON STRZERO(DEZ2,2) TAG DEZ2 TO RANKING INDEX ON DESCEND( STRZERO(RPT2,2) ) TAG RPT2 TO RANKING INDEX ON STRZERO(RNK2,2) TAG RNK2 TO RANKING INDEX ON STRZERO(DEZ3,2) TAG DEZ3 TO RANKING INDEX ON DESCEND(STRZERO(RPT3,2) ) TAG RPT3 TO RANKING INDEX ON STRZERO(RNK3,2) TAG RNK3 TO RANKING INDEX ON STRZERO(DEZ4,2) TAG DEZ4 TO RANKING INDEX ON DESCEND(STRZERO(RPT4,2) ) TAG RPT4 TO RANKING INDEX ON STRZERO(RNK4,2) TAG RNK4 TO RANKING INDEX ON STRZERO(DEZ5,2) TAG DEZ5 TO RANKING INDEX ON DESCEND(STRZERO(RPT5,2) ) TAG RPT5 TO RANKING INDEX ON STRZERO(RNK5,2) TAG RNK5 TO RANKING INDEX ON STRZERO(DEZ6,2) TAG DEZ6 TO RANKING INDEX ON DESCEND(STRZERO(RPT6,2) ) TAG RPT6 TO RANKING INDEX ON STRZERO(RNK6,2) TAG RNK6 TO RANKING SET INDEX TO RANKING // ABRINDO ARQUIVO DE ÍNDICES ? TIME()+" - LEVANTANDO INFORMAÇÕES SOBRE CADA BOLA SORTEADA..." // VAMOS CRIAR 60 REGISTROS EM BRANCO P/ GUARDAR AS INFORMAÇÕES FOR X=1 TO 60 RNK->(DBAPPEND()) NEXT ? "1ª BOLA:" ? TIME()+" - VERIFICANDO QUANTAS VEZES CADA DEZENA FOI SORTEADA..." RNK->(ORDSETFOCUS("DEZ1")) // POR ORDEM DE DEZENA DEZ->(DBGOTOP()) RNK->(DBGOTOP()) DO WHILE !DEZ->(EOF()) IF !RNK->(DBSEEK( STRZERO(DEZ->DEZ1,2) )) RNK->(DBGOTOP()) // POSICIONA NO INICIO DO ARQUIVO DO WHILE !EMPTY(RNK->DEZ1) // DESCE ATÉ ACHAR UM CAMPO EM BRANCO RNK->(DBSKIP()) ENDDO RNK->DEZ1 := DEZ->DEZ1 RNK->RPT1 := 1 ELSE RNK->RPT1++ ENDIF DEZ->(DBSKIP()) ENDDO ? TIME()+" - FAZENDO O RANKING DAS MAIS SORTEADAS..." RNK->(ORDSETFOCUS("RPT1")) // POR ORDEM DE REPETIÇÃO DA DEZENA RNK->(DBGOTOP()) nRANK := 1 DO WHILE !RNK->(EOF()) RNK->RNK1 := nRANK++ RNK->(DBSKIP()) ENDDO ? "2ª BOLA:" ? TIME()+" - VERIFICANDO QUANTAS VEZES CADA DEZENA FOI SORTEADA..." RNK->(ORDSETFOCUS("DEZ2")) // POR ORDEM DE DEZENA DEZ->(DBGOTOP()) RNK->(DBGOTOP()) DO WHILE !DEZ->(EOF()) IF !RNK->(DBSEEK( STRZERO(DEZ->DEZ2,2) )) RNK->(DBGOTOP()) // POSICIONA NO INICIO DO ARQUIVO DO WHILE !EMPTY(RNK->DEZ2) // DESCE ATÉ ACHAR UM CAMPO EM BRANCO RNK->(DBSKIP()) ENDDO RNK->DEZ2 := DEZ->DEZ2 RNK->RPT2 := 1 ELSE RNK->RPT2++ ENDIF DEZ->(DBSKIP()) ENDDO ? TIME()+" - FAZENDO O RANKING DAS MAIS SORTEADAS..." RNK->(ORDSETFOCUS("RPT2")) // POR ORDEM DE REPETIÇÃO DA DEZENA RNK->(DBGOTOP()) nRANK := 1 DO WHILE !RNK->(EOF()) RNK->RNK2 := nRANK++ RNK->(DBSKIP()) ENDDO ? "3ª BOLA:" ? TIME()+" - VERIFICANDO QUANTAS VEZES CADA DEZENA FOI SORTEADA..." RNK->(ORDSETFOCUS("DEZ3")) // POR ORDEM DE DEZENA DEZ->(DBGOTOP()) RNK->(DBGOTOP()) DO WHILE !DEZ->(EOF()) IF !RNK->(DBSEEK( STRZERO(DEZ->DEZ3,2) )) RNK->(DBGOTOP()) // POSICIONA NO INICIO DO ARQUIVO DO WHILE !EMPTY(RNK->DEZ3) // DESCE ATÉ ACHAR UM CAMPO EM BRANCO RNK->(DBSKIP()) ENDDO RNK->DEZ3 := DEZ->DEZ3 RNK->RPT3 := 1 ELSE RNK->RPT3++ ENDIF DEZ->(DBSKIP()) ENDDO ? TIME()+" - FAZENDO O RANKING DAS MAIS SORTEADAS..." RNK->(ORDSETFOCUS("RPT3")) // POR ORDEM DE REPETIÇÃO DA DEZENA RNK->(DBGOTOP()) nRANK := 1 DO WHILE !RNK->(EOF()) RNK->RNK3 := nRANK++ RNK->(DBSKIP()) ENDDO ? "4ª BOLA:" ? TIME()+" - VERIFICANDO QUANTAS VEZES CADA DEZENA FOI SORTEADA..." RNK->(ORDSETFOCUS("DEZ4")) // POR ORDEM DE DEZENA DEZ->(DBGOTOP()) RNK->(DBGOTOP()) DO WHILE !DEZ->(EOF()) IF !RNK->(DBSEEK( STRZERO(DEZ->DEZ4,2) )) RNK->(DBGOTOP()) // POSICIONA NO INICIO DO ARQUIVO DO WHILE !EMPTY(RNK->DEZ4) // DESCE ATÉ ACHAR UM CAMPO EM BRANCO RNK->(DBSKIP()) ENDDO RNK->DEZ4 := DEZ->DEZ4 RNK->RPT4 := 1 ELSE RNK->RPT4++ ENDIF DEZ->(DBSKIP()) ENDDO ? TIME()+" - FAZENDO O RANKING DAS MAIS SORTEADAS..." RNK->(ORDSETFOCUS("RPT4")) // POR ORDEM DE REPETIÇÃO DA DEZENA RNK->(DBGOTOP()) nRANK := 1 DO WHILE !RNK->(EOF()) RNK->RNK4 := nRANK++ RNK->(DBSKIP()) ENDDO ? "5ª BOLA:" ? TIME()+" - VERIFICANDO QUANTAS VEZES CADA DEZENA FOI SORTEADA..." RNK->(ORDSETFOCUS("DEZ5")) // POR ORDEM DE DEZENA DEZ->(DBGOTOP()) RNK->(DBGOTOP()) DO WHILE !DEZ->(EOF()) IF !RNK->(DBSEEK( STRZERO(DEZ->DEZ5,2) )) RNK->(DBGOTOP()) // POSICIONA NO INICIO DO ARQUIVO DO WHILE !EMPTY(RNK->DEZ5) // DESCE ATÉ ACHAR UM CAMPO EM BRANCO RNK->(DBSKIP()) ENDDO RNK->DEZ5 := DEZ->DEZ5 RNK->RPT5 := 1 ELSE RNK->RPT5++ ENDIF DEZ->(DBSKIP()) ENDDO ? TIME()+" - FAZENDO O RANKING DAS MAIS SORTEADAS..." RNK->(ORDSETFOCUS("RPT5")) // POR ORDEM DE REPETIÇÃO DA DEZENA RNK->(DBGOTOP()) nRANK := 1 DO WHILE !RNK->(EOF()) RNK->RNK5 := nRANK++ RNK->(DBSKIP()) ENDDO ? "6ª BOLA:" ? TIME()+" - VERIFICANDO QUANTAS VEZES CADA DEZENA FOI SORTEADA..." RNK->(ORDSETFOCUS("DEZ6")) // POR ORDEM DE DEZENA DEZ->(DBGOTOP()) RNK->(DBGOTOP()) DO WHILE !DEZ->(EOF()) IF !RNK->(DBSEEK( STRZERO(DEZ->DEZ6,2) )) RNK->(DBGOTOP()) // POSICIONA NO INICIO DO ARQUIVO DO WHILE !EMPTY(RNK->DEZ6) // DESCE ATÉ ACHAR UM CAMPO EM BRANCO RNK->(DBSKIP()) ENDDO RNK->DEZ6 := DEZ->DEZ6 RNK->RPT6 := 1 ELSE RNK->RPT6++ ENDIF DEZ->(DBSKIP()) ENDDO ? TIME()+" - FAZENDO O RANKING DAS MAIS SORTEADAS..." RNK->(ORDSETFOCUS("RPT6")) // POR ORDEM DE REPETIÇÃO DA DEZENA RNK->(DBGOTOP()) nRANK := 1 DO WHILE !RNK->(EOF()) RNK->RNK6 := nRANK++ RNK->(DBSKIP()) ENDDO RNK->(DBCOMMIT()) CLOSE ALL ? ? "INFORMAÇÕES COMPLETAS!" ? "PRESSIONE UMA TECLA P/ CONTINUAR" INKEY(0) ENDIF ENDIF *** PARTE DO PROGRAMA QUE SORTEIA OS NÚMEROS ***------------------------- USE RANKING ALIAS RNK EXCLUSIVE NEW SET INDEX TO RANKING RNK->(ORDSETFOCUS("RPT1")) // POR REPETIÇÃO/OCORRENCIA RNK->(DBGOTOP()) CLS @ 00,00 SAY PADC("*** Ranking da MEGA SENA ***",80) @ 01,00 SAY PADC("Sorteia no Ranking dos sorteios",80) nAPOSTAS := nDE := nATE := nDEZENAS := 0 @ 03,10 SAY "QUANTAS APOSTAS?.............:" GET nAPOSTAS PICT "999" * @ 04,10 SAY "CARTELA DE (6-10)............:" GET nDEZENAS RANGE 6,10 PICT "99" @ 04,10 SAY "CARTELA DE 6 DEZENAS"; nDEZENAS := 6 @ 05,10 SAY "CLASSIFICAÇÃO ENTRE..........:" GET nDE PICT "99" @ 05,44 SAY "E" GET nATE PICT "99" VALID nATE > nDE READ @ 07,00 SAY "Números sorteados entre "+str(nDE,2)+" e "+STR(nATE,2)+" do Ranking:" LL := 9 SETPOS(LL,00) aCARTELA := {} // CONTROLAR NUMEROS DA CARTELA PARA NAO REPETIR aJOGOS := {} aEMPATE := {} FOR X=1 TO nAPOSTAS FOR S=1 TO nDEZENAS // aCARTELA TERÁDEZENAS DO WHILE .T. RNK->(ORDSETFOCUS("RNK"+STR(S,1) )) RNK->(DBGOTOP()) // SORTEIA ENTRE A CLASSIFICAÇÃO DO RANKING ESCOLHIDA nSORTE := HB_RANDOMINT(nDE, nATE ) nSORTE := STRZERO(nSORTE,2) RNK->(DBSEEK(nSORTE)) // POSICIONA NA DEZENA DE NÚMERO DO RANKING bDEZ := &( "{|| RNK->DEZ"+STR(S,1)+" }" ) // CODEBLOCK COM O NOME DO CAMPO nDEZ := EVAL( bDEZ ) // VALOR DO CAMPO // TESTA SE HÁ EMPATADOS NO RANKING bRPT := &( "{|| RNK->RPT"+STR(S,1)+" }" ) // CODEBLOCK COM O NOME DO CAMPO nRPT := EVAL( bRPT ) // VALOR QUE A DEZENA SE REPETIU P/ OCUPAR ESTE LUGAR NO RANKING RNK->(ORDSETFOCUS("RPT"+STR(S,1) )) RNK->(DBGOTOP()) RNK->(DBSEEK( STRZERO(nRPT,2) )) // POSICIONA NA 1ª DEZENA QUE SE REPETIU IGUAL A DEZENA SORTEADA DO RANKING RNK->(DBSKIP()) IF EVAL(bRPT) = nRPT // HÁ EMPATADOS? DO WHILE EVAL(bRPT) = nRPT // FAÇA ENQUANTO MESMA REPETIÇÃO DA DEZENA NO RANKING aADD(aEMPATE, EVAL(bDEZ) ) RNK->(DBSKIP()) ENDDO nEMPATES := LEN(aEMPATE) IF nEMPATES > 0 // HÁ EMPATES NO RANKING nSORTE := HB_RANDOMINT(1, nEMPATES ) nDEZ := aEMPATE[nSORTE] // SORTEIA UM ENTRE OS EMPATADOS DO RANKING ENDIF aEMPATE := {} // ZERA MATRIZ DE EMPATES ENDIF IF aSCAN(aCARTELA, nDEZ) > 0 // JÁ SORTEIOU ESTA DEZENA NESTA CARTELA LOOP // VOLTA ENDIF aADD(aCARTELA, nDEZ) EXIT ENDDO NEXT aSORT(aCARTELA) // COLOCA MATRIZ DAS 6 DEZENAS EM ORDEM CRESCENTE // FACILITA IDENTIFICAÇÃO E ANULAÇÃO DE CARTELAS IGUAIS *** MOSTRA DEZENAS SORTEADAS NA TELA FOR T=1 TO nDEZENAS @ LL,COL()+2 SAY aCARTELA[T] NEXT SETPOS(++LL,0) *** TESTA SE NÃO HÁ CARTELAS IGUAIS IF aSCAN(aJOGOS, aCARTELA) > 0 // SE JÁ TEM aCARTELA EM aJOGOS LOOP // SE JÁ TEM, VOLTA E REPETE SORTEIO DA CARTELA ENDIF aADD(aJOGOS, aCARTELA) // ACRESCENTA aCARTELA EM aJOGOS aCARTELA := {} // NOVA CARTELA ZERADA NEXT INKEY(0)
Estava faltando descomplicar...
Para enviar emails pelo xHarbour é melhor utilizar a função SendMail que estamos anexando a esta matéria no rodapé para download.
Veja sua sintaxe:
FUNCTION HB_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aFiles, cUser, cPass, cPopServer, nPriority, lRead, lTrace, lPopAuth, lnoauth, nTimeOut) /* cServer -> Obrigatório. IP ou domínio do servidor de emails nPort -> Opcional. Porta usada pelo servidor de emails cFrom -> Obrigatório. Email do remetente aTo -> Obrigatório. String ou array de endereços de email para serem enviados aCC -> Opcional. String ou array de endereços de email para CC (Carbon Copy) aBCC -> Opcional. String ou array de endereços de email para BCC (Blind Carbon Copy) cBody -> Opcional. A mensagem do corpo do email como texto ou arquivo HTML cSubject -> Opcional. Assunto do email aFiles -> Opcional. Array de arquivos para serem enviados como anexo cUser -> Obrigatório. Nome de usuário do servidor POP3 cPass -> Obrigatório. Senha do cUser cPopServer -> Obrigatório. Nome ou endereço do servidor de emails POP3 [sic][Usa-se o SMTP para enviar email] nPriority -> Opcional. Prioridade do Email: 1=Alta, 3=Normal (Padrão), 5=Baixa lRead -> Opcional. Se for .T., uma requisição de confirmação será solicitada. Por padrão é .F. lTrace -> Opcional. Se for .T., um arquivo de log é criado (sendmail.log). O padrão é .F. lnoauth -> Opcional. Desativa método de autenticação nTimeOut -> Opcional. Número de milisegundos para esperar. O padrão é 20000 (20s). */
Veja um exemplo de minha autoria para enviar emails pelo xHarbour com o SendMail:
IF (ALERT("ENVIA ARQUIVOS POR EMAIL AGORA?", {"Sim", "Não"})) = 1 @ 24,00 SAY PADC("Preparando email... AGUARDE!",80) COLOR "W+/BG" // ARQUIVOS A SEREM ENVIADOS aFILES := {cPASTA+cARQLC, cPASTA+cARQLI, cPASTA+cARQCON} // COMPACTA ARQUIVOS fZIP := cPASTA+"Portal.zip" IF FILE(fZIP) RUN ("DEL "+fZIP) // APAGA ZIP ANTERIOR ENDIF HB_ZIPFILE(fZIP, aFILES) // COMPACTA OS 3 ARQUIVOS EM PORTAL.ZIP // preparing data for eMail cSubject := "Aqui vai o assunto do seu email" cFrom := "email@remetente.com.br" // email do remetente cMAILUSER := "usuariodoemail" // login de acesso do seu email cPASSWORD := "senhadoemail" // sua senha de email cSMTP := "smtp.seudominio.com.br" // seu domínio do email cTo := "email@destinatario.com.br" // email do destinatário cCC := cFrom // manda cópia carbono pra você mesmo ter certeza que deu certo aAttach := {fZIP} // sempre array cBody := "Prezados,"+HB_OsNewLine()+HB_OsNewLine()+; HB_OemToAnsi("Estamos encaminhando as informações da STU-MAC/CBTU para o Portal da Transparência referente ao período de "; +DTOC(dINIPROC)+" a "+DTOC(dFIMPROC)+".")+HB_OsNewLine()+; "Atenciosamente,"+HB_OsNewLine()+HB_OsNewLine()+; "Fulano de Tal"+HB_OsNewLine()+; "Cargo/empresa"+HB_OsNewLine()+; "Fone: (99) 9999-9999" nEMAILSIZE := HB_FSIZE(fZIP) / 1024 @ 24,00 SAY PADC("Enviando arquivo Portal.zip por email... ("+ALLTRIM(STR(nEMAILSIZE))+"Kb) AGUARDE!",80) COLOR "W+/BG" IF HB_SENDMAIL(cSMTP,, cFROM, cTO, cCC,, cBODY, cSUBJECT, aAttach, cMAILUSER, cPASSWORD, cSMTP, 1, .T., .T.) ALERT("ARQUIVOS ENVIADOS COM ÊXITO.") ELSE ALERT("Falha ao enviar o email.") ENDIF ENDIF
Enviar emails pelo sistema pode ser útil quando você tem que mandar um email para vários destinatários, ninguém pode conhecer o email do outro (para evitar conluios) e você precisa do comprovante de envio (prova de pesquisa de mercado). Assim, não adianta mandar via BCC, pois não vai ter comprovante.