Digite assunto para busca:

PROGRAMAÇÃO/FISCAL: Cálculo de impostos em uma nota fiscal (000316-13/6/2010)

Podem ocorrer variações na forma de cálculo, portanto vamos apresentar aqui a forma mais comum, utilizada na maioria dos casos.

IPI - Imposto sobre produtos industrializados
ICMS - Imposto sobre circulação de mercadorias
ISS - Imposto sobre serviços
PIS
Cofins
ICMS-ST - ICMS Substituição Tributária

Nomenclatura: INT() - retorna apenas a parte inteira do resultado, desprezando decimais.

IPI

O IPI é sobre o valor do produto, e acrescentado ao total da nota.
Para o cálculo do IPI, precisamos saber do percentual do imposto, que varia conforme produto.

nValordoProduto = 10.000,00
nPercentualIpi = 10
nValorIpi = Int( nValordoProduto * nPercentalIpi ) / 100 = 1.000


ICMS

O ICMS é o imposto sobre a circulação da mercadoria. Dependendo do tipo de operação, pode ou não ter ICMS.
Há casos de redução da base de cálculo, onde apenas uma parte do valor sofre cálculo de ICMS.
Para o cálculo do ICMS, percisamos da alíquota de imposto e da alíquota de redução, que pode ser zero.
No cálculo do ICMS, o valor do IPI (Se houver) geralmente é somado ao valor do produto.

nValorProduto = 10.000
nValorIpi = 1.000
nAliqIcms = 12
nAliqReducao = 10

nBaseIcms = ( nValorProduto + nValorIpi )
nReducao = Int( nBaseIcms * nAliqReducao ) / 100
nBaseIcms = nBaseIcms - nReducao
nValorIcms = ( nBaseIcms * nAliqIcms ) / 100


ICMS-ST

O ICMS Substituição é calculado sobre um valor previsto para venda.
Do resultado do cálculo é abatido o ICMS normal, cujo cálculo já foi apresentado acima.
Para o cálculo do ICMS-ST necessitamos do percentual do IVA, alíquota de ICMS-ST, e percentual de redução da base de cálculo de ICMS-ST.
Estas alíquotas podem ou não ser iguais à alíquotas do ICMS normal.
O Valor do ICMS-ST é somado ao valor total da nota fiscal.

nBaseSub = (ValorProduto+ValorIpi)
nBaseSub = nBaseSub + ( (nBaseSub * nAliqIVA) / 100)
nReducao = Int( nBaseSub * nAliqRed ) / 100
nBaseSub = nBaseSub - nReducao
nValorSub = Int( nBaseSub * nAliqSub ) / 100
nValorSub = nValorSub - nValorICMS


PIS/COFINS

O PIS é calculado sobre o valor total do produto. (valor + IPI).
Apenas aplica-se a alíquota ao valor do produto.

ISS

O ISS é calculado sobre o valor do serviço.
Aplica-se a alíquota ao valor do serviço.

PROGRAMAÇÃO: Tabelas Sped (CFOP, ICMS, CST, Cidades, etc) (000315-12/6/2010)

Temos várias tabelas no Sped.
Temos CFOP, CST, Cidades do IBGE, UFs, países, etc.
Um bom lugar pra encontrar essas tabelas está neste link:

Tabelas Sped

PROGRAMAÇÃO: MySql pra quem usa xbase (000314-7/6/2010)

Muitos divulgam LIBs pra facilitar acesso a MySql.
O uso de LIBs é bom, pois quando se tem muito fonte a ser alterado, elas reduzem o tempo necessário para a mudança deles.
Só que o uso estilo xbase não vai usar NENHUM recurso do MySql, e ao contrário, pode deixar tudo mais lento, e o servidor mais sobrecarregado.

Base de Dados

A base de dados é simplesmente o armazenamento dos dados.
Você salva e busca dados.
Isto é a base tradicional dos DBFs. Só salvar e buscar, e mais nada.

SQL/MySql

No MySql, trata-se de um gerenciamento de base de dados.
É um servidor, com programação própria, que lhe entrega tudo pronto.
Basta um comando SQL e todo processamento já vém pronto.

Exemplos práticos:

Imaginem um banco de dados com duas tabelas:
NOTAS FISCAIS: NUMERO, CODCLIENTE, DATAEMISSAO, VALOR
CLIENTES: CODCLIENTE, NOME

Vamos pegar um relatório médio:
- Somente totais por cliente
- Em ordem alfabética (em ordem de valores, o fonte ficaria muito grande)
- Somente valores acima de 5000

select 0
use notas index codcliente
select 0
use clientes index nome
Goto Top
Do While .Not. Eof()
mSoma := 0
Select notas
Seek clientes->CodCliente
Do While clientes->CodCliente == notas->CodCliente .And. .Not. Eof()
mSoma := mSoma + notas->Valor
Skip
Enddo
select clientes
If mSoma < 5000
Skip
Loop
Endif
@ Row(), 0 Say notas->numero
@ Row(), Col()+2 say notas->codcliente
@ Row(), Col()+2 say clientes->Nome
@ Row(), Col()+2 Say notas->DataEmissao
@ Row(), Col()+2 Say notas->Valor
@ Row()+1, 0 Say ""
Skip
Enddo
close databases


Legal, funciona direito, e se usar uma lib Mysql não precisa mexer no fonte.
Vai acessar o Mysql durante o relatório inteiro, processar TODOS os registros do banco de dados, que irão chegar via rede, ou via internet.
Vai estar usando muito o servidor MySql, mas NADA/ZERO de seus recursos.
Numa base de 10.000 notas, e 1.000 clientes, vai estar trazendo para o terminal 11.000 registros, via rede ou via internet, e também fazendo várias consultas durante o relatório.

Já usando recursos do MySql...
Uma única consulta ao banco e já teria o relatório pronto.

SELECT CODCLIENTE, NOME, SUM(VALOR) SOMA FROM NOTAS GROUP BY CODCLIENTE WHERE SOMA > 5000 ORDER BY NOME


Digamos que existam 100 clientes que atendam essa condição.
No estilo xbase, haverá o tráfego de 11.000 registros pela rede/internet, e várias consultas à base MySql.
Usando recurso do MySql, com a query acima, haverá o tráfego de somente 100 registros pela rede/internet, em uma única consulta à base MySql.
Diferença mais prática?
Suponha a base na internet, e 100 bytes cada registro.
11.000 registros x 100 bytes = 1.100.000 bytes = 1.1MB
100 registros x 100 bytes = 10.000 bytes = 10kb
Numa banda larga de 1MB, que baixa a uns 100kb, o primeiro demora 11 segundos, e o segundo apenas meio segundo, isso sem contar as várias solicitações ao servidor executadas na primeira opção, senão será uma diferença ainda maior.
O programa fica muito mais rápido, e com menos fonte.

Agora, imagine as possibilidades....
Imagine que o relatório poderia ser por ordem de valor.
O fonte em xbase seria muito maior, já em SQL, só mudaria o ORDER BY.
E se fosse total por data?
O fonte em xbase seria diferente, já em SQL, só mudaria o GROUP BY

O SQL permite:
- Totalizar dados (reduz tráfego de dados)
- Relacionar tabelas (reduz consultas)
- Colocar em determinada ordem (reduz processamento local)
- Filtrar dados (reduz tráfego de dados)

Essa é só uma pequena parte das diferenças entre os DBFs e os bancos de dados relacionais.
Ficar preso ao estilo xbase não é interessante.

Ahhh... o fonte modificado... bom, depende da LIB ou linguagem.
Como o ADO é padrão, e no xHarbour fica igual, vai um simbólico meio xHarbour/VB...

Set Rs = Conexao.Execute("SELECT CODCLIENTE, NOME, SUM(VALOR) SOMA FROM NOTAS GROUP BY CODCLIENTE WHERE SOMA > 5000 ORDER BY NOME")
Rs.MoveFirst
Do While Not Rs.Eof()
? rs.Fields("NUMERO").Value
? rs.Fields("CODCLIENTE").Value
? rs.Fields("NOME").Value
? rs.Fields("DATAEMISSAO").Value
? rs.Fields("VALOR").Value
Rs.MoveNext
Loop
Rs.Close


Obs. Uso o ADS no VB, e tudo isso também é permitido. Tudo bem, ADS usa DBF/CDX , mas ADS é um servidor de banco de dados, e não apenas DBF/CDX.

PROGRAMAÇÃO: Gerando XML de Nota Fiscal Eletrônica (000312-3/6/2010)

Basicamente o XML é composto de tags.
A tag começa com [tag] e termina com [/tag]
E uma tag pode conter sub-tags.

O cnpj do emitente ficaria assim:

mXml = "[cnpj]" + emitente-]cnpj + "[/cnpj]"


O nome do emitente ficaria assim:

mXml = "[nome]" + emitente-]nome + "[/nome]"


E o conjunto de dados do emitente ficaria assim:

mXml = "[emitente]" + ,
"[cnpj]" + emitente-]cnpj + "[/cnpj]" + ,
"[nome]" + emitente-]nome + "[/nome]" + ,
"[/emitente]"



Nos exemplos acima, vemos que a parte mais chata é ficar abrindo e fechando tags.
Pra isso, criamos uma função, só precisando passar o nome e o conteúdo.

E pode confundir o abrir/fechar, quando o Xml vai ficando extenso.
Então vamos separar em blocos.
Abaixo um fonte mais completo, só pra dar uma idéia.

mXmlNota = XmlTag("nota",notafiscal-]numero) + ,
XmlTag("emissao",Dtos(notafiscal-]emissao)) + ,
XmlTag("natureza",notfiscal-]natureza)

mXmlEmitente = XmlTag("cnpj",emitente-]cnpj) + ,
XmlTag("nome",emitente-]nome) + ,
XmlTag("endereco",emitente-]endereco) + ,
XmlTag("cidade",emitente-]cidade) + ,
XmlTag("UF", emitente-]uf)

mXmlDestinatario = XmlTag("cnpj",cliente-]cnpj) + ,
XmlTag("nome",emitente-]nome) + ,
XmlTag("endereco",emitente-]endereco) + ,
XmlTag("cidade",emitente-]cidade) + ,
XmlTag("UF",emitente-]UF)

mXmlProduto = XmlTag("produto",produto-]nome) + ,
XmlTag("Qtde",Ltrim(Str(produto-]Qtde,16,2))) + ,
XmlTag("Valor",Ltrim(Str(produto-]Valor,16,4)))

mXmlGeral = ,
XmlTag("Nota",mXmlNota) + ,
XmlTag("emitente",mXmlEmitente) + ,
XmlTag("destinatario",mXmlDestinatario") + ,
XmlTag("produto",mXmlProduto)

MemoWrit(ArquivoXml,mXmlGeral)

Function XmlTag(cTag, cConteudo)
Local cTexto = ""
cTexto = "[" + cTag + "]" + cConteudo + "[/" + cTag + "]"
Return cTexto


Há várias formas de fazer tudo isso. Basta escolher a que achar melhor.

Esse fonte é simples e prático.
Tem um componente da Microsoft pra XML, mas é bem mais complexo.

** Substituir [] por menor/maior. É que menor/maior é controle de página de internet, e estavam sendo omitidos do fonte

PROGRAMAÇÃO: VB6 Esperando alguns segundos (000294-4/3/2010)

Uma opção para fazer uma pausa dentro do VB6, sem travar o programa, é esta.
O fonte não é de minha autoria, e pode ser encontrado nas páginas da Microsoft.

Referência Microsoft: Q231298
Option Explicit

Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type

Private Const WAIT_ABANDONED& = &H80&
Private Const WAIT_ABANDONED_0& = &H80&
Private Const WAIT_FAILED& = -1&
Private Const WAIT_IO_COMPLETION& = &HC0&
Private Const WAIT_OBJECT_0& = 0
Private Const WAIT_OBJECT_1& = 1
Private Const WAIT_TIMEOUT& = &H102&

Private Const INFINITE = &HFFFF
Private Const ERROR_ALREADY_EXISTS = 183&

Private Const QS_HOTKEY& = &H80
Private Const QS_KEY& = &H1
Private Const QS_MOUSEBUTTON& = &H4
Private Const QS_MOUSEMOVE& = &H2
Private Const QS_PAINT& = &H20
Private Const QS_POSTMESSAGE& = &H8
Private Const QS_SENDMESSAGE& = &H40
Private Const QS_TIMER& = &H10
Private Const QS_MOUSE& = (QS_MOUSEMOVE _
Or QS_MOUSEBUTTON)
Private Const QS_INPUT& = (QS_MOUSE _
Or QS_KEY)
Private Const QS_ALLEVENTS& = (QS_INPUT _
Or QS_POSTMESSAGE _
Or QS_TIMER _
Or QS_PAINT _
Or QS_HOTKEY)
Private Const QS_ALLINPUT& = (QS_SENDMESSAGE _
Or QS_PAINT _
Or QS_TIMER _
Or QS_POSTMESSAGE _
Or QS_MOUSEBUTTON _
Or QS_MOUSEMOVE _
Or QS_HOTKEY _
Or QS_KEY)

Private Declare Function CreateWaitableTimer Lib "kernel32" _
Alias "CreateWaitableTimerA" ( _
ByVal lpSemaphoreAttributes As Long, _
ByVal bManualReset As Long, _
ByVal lpName As String) As Long

Private Declare Function OpenWaitableTimer Lib "kernel32" _
Alias "OpenWaitableTimerA" ( _
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal lpName As String) As Long

Private Declare Function SetWaitableTimer Lib "kernel32" ( _
ByVal hTimer As Long, _
lpDueTime As FILETIME, _
ByVal lPeriod As Long, _
ByVal pfnCompletionRoutine As Long, _
ByVal lpArgToCompletionRoutine As Long, _
ByVal fResume As Long) As Long

Private Declare Function CancelWaitableTimer Lib "kernel32" ( _
ByVal hTimer As Long)

Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long

Private Declare Function WaitForSingleObject Lib "kernel32" ( _
ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long

Private Declare Function MsgWaitForMultipleObjects Lib "user32" ( _
ByVal nCount As Long, _
pHandles As Long, _
ByVal fWaitAll As Long, _
ByVal dwMilliseconds As Long, _
ByVal dwWakeMask As Long) As Long

Public Sub Api_Wait(lNumberOfSeconds As Long)
Dim ft As FILETIME
Dim lBusy As Long
Dim lRet As Long
Dim dblDelay As Double
Dim dblDelayLow As Double
Dim dblUnits As Double
Dim hTimer As Long

hTimer = CreateWaitableTimer(0, True, App.EXEName & "Timer")

If err.LastDllError = ERROR_ALREADY_EXISTS Then
If the timer already exists, it does not hurt to open it
as long as the person who is trying to open it has the
proper access rights.
Else
ft.dwLowDateTime = -1
ft.dwHighDateTime = -1
lRet = SetWaitableTimer(hTimer, ft, 0, 0, 0, 0)
End If

Convert the Units to nanoseconds.
dblUnits = CDbl(&H10000) * CDbl(&H10000)
dblDelay = CDbl(lNumberOfSeconds) * 1000 * 10000

By setting the high/low time to a negative number, it tells
the Wait (in SetWaitableTimer) to use an offset time as
opposed to a hardcoded time. If it were positive, it would
try to convert the value to GMT.
ft.dwHighDateTime = -CLng(dblDelay / dblUnits) - 1
dblDelayLow = -dblUnits * (dblDelay / dblUnits - _
Fix(dblDelay / dblUnits))

If dblDelayLow < CDbl(&H80000000) Then
&H80000000 is MAX_LONG, so you are just making sure
that you dont overflow when you try to stick it into
the FILETIME structure.
dblDelayLow = dblUnits + dblDelayLow
ft.dwHighDateTime = ft.dwHighDateTime + 1
End If

ft.dwLowDateTime = CLng(dblDelayLow)
lRet = SetWaitableTimer(hTimer, ft, 0, 0, 0, False)

Do
QS_ALLINPUT means that MsgWaitForMultipleObjects will
return every time the thread in which it is running gets
a message. If you wanted to handle messages in here you could,
but by calling Doevents you are letting DefWindowProc
do its normal windows message handling---Like DDE, etc.
lBusy = MsgWaitForMultipleObjects(1, hTimer, False, _
INFINITE, QS_ALLINPUT&)
DoEvents
Loop Until lBusy = WAIT_OBJECT_0

Close the handles when you are done with them.
CloseHandle hTimer

End Sub

PROGRAMAÇÃO Clipper: Arquivo de CEP dos correios (000211-1/4/2008)

Este download é de um arquivo DBF contendo CEPs e respectivos endereços.
O download é apenas para ajudar usuários do Clipper.
O JPA não necessita deste arquivo, visto que já faz consulta on-line nos correios.

Obs.
Não disponibilizaremos o método que usamos para fazer a consulta on-line.
Infelizmente muitos principiantes querem baixar bases extremamente atualizadas, e isso é impossível pela quantidade de CEPs existentes, o máximo que conseguem é sobrecarregar os servidores dos correios e podem acabar causando o bloqueio definitivo das consultas.

Em todo caso, pode baixar nosso arquivo DBF contendo CEPs do Brasil inteiro.
O formato é LZH, caso não possua descompactador, aqui no site você também encontra o LHA.EXE, que é um programa livre para compactação e descompactação..

Base de CEPs em LZH

PROGRAMAÇÃO Clipper: Geração de TXT para programa da Fazenda (000206-1/4/2008)

Apenas como ajuda, abaixo uma rotina para gerar dados do emitente.
Pode ser usada como base pra gerar a nota fiscal eletrônica.
Para obter um exemplo de arquivo, basta digitar os dados no programa da Fazenda e exportar o arquivo.
O arquivo de NFE já possui todos os dados necessários ao programa da Fazenda. Os cadastros de cliente, produtos, transportadoras, etc. só é necessário caso precise digitar notas diretamente no programa da Fazenda.
Imprima o manual em papel. É uma ótima forma de conferir o resultado.
Atenção ao conjunto de caracteres válidos: alguns símbolos e letras acentuadas não são aceitos, gerando erro.
É obrigatório guardar os arquivos XML gerados pelo programa da Fazenda. Somente ao final do processo é que o arquivo XML contém o protocolo de autorização fornecido pela Fazenda. Estes arquivos devem ser armazenados por no mínimo 5 anos, e devem ficar à disposição da fiscalização.
Os campos com decimais devem conter todas as casas decimais. Exemplo: 2.00 se o campo contiver duas casas decimais. As casas decimais são obrigatórias.
Espaços em branco: Na maioria dos campos eles devem ser removidos. Mas existem algumas exceções

Procedure GeraNfeEmi(mFileTxt)

mTraco := "|"
mCrLf := Chr(13) + Chr(10)

Set Alternate To ("nfe"+mFileTxt)
Set Alternate On
Set Console Off

?? "EMITENTE"
?? mTraco
?? "1"
?? mTraco
?? " "
?? mCrLf

?? "A"
?? mTraco
?? "1.01"
?? mTraco
?? " "
?? mCrLf

?? "C"
?? mTraco
?? "CNPJ"
?? mTraco
?? SoNumeros(jpempre->emCnpj)
?? mTraco
?? Trim(jpempre->emNome)
?? mTraco
?? Trim(jpempre->emNome)
?? mTraco
?? SoNumeros(jpempre->emIE)
?? mTraco
?? " "
?? mTraco
?? " "
?? mTraco
?? " "
?? mTraco
?? Trim(jpempre->emEndereco)
?? mTraco
?? "."
?? mTraco
?? ""
?? mTraco
?? Trim(jpempre->emBairro)
?? mTraco
?? CidadeIbge(jpempre->emCidade,jpempre->emUf)
?? mTraco
?? Trim(jpempre->emCidade)
?? mTraco
?? jpempre->emUf
?? mTraco
?? SoNumeros(jpempre->emCep)
?? mTraco
?? "1058"
?? mTraco
?? "BRASIL"
?? mTraco
?? ""
?? mTraco
?? " "
// ?? mCrLf

Set Console On
Set Alternate Off
Set Alternate To
DelCtrlZ("nfe"+mFileTxt)

Return

PROGRAMAÇÃO: Validar XML de NFE (000338-31/8/2010)

Pra validar um XML de nota fiscal eletrônica, há uma rotina no site da Secretaria da Fazenda do Rio Grande do Sul.
Basta acessar o site e validar o XML.

http://www.sefaz.rs.gov.br/NFE/NFE-VAL.aspx

PROGRAMAÇÃO HTML: Template para estilos de table (000324-5/7/2010)

Um bom lugar pra testar estilos a serem utilizados em table.
Conforme vai testando, é gerado o código fonte, e também apresentado o modelo.

somacon

PROGRAMAÇÃO: Converter Clipper pra xHarbour (000318-21/6/2010)

Num primeiro momento, tudo que o xHarbour aceita, o Clipper também.
Isso significa que durante os testes pode usar os mesmos fontes nos dois.
Vai poder alterar seu fonte normal, rodar no clipper, e testar no xHarbour.
Nada melhor pra teste do que ter os mesmos fontes, tendo certeza de que estão corretos.

No Clipper o default é que o nome do programa é o mesmo nome que está no fonte (nome.prg).
Ao compilar com /N, o nome do fonte é desprezado, e vale o que estiver dentro do fonte.
Este é o default do xHarbour.

Então... iniciando...

1. Primeiro verifique o que está usando além do Clipper, pra ver se vai ter tudo na mão.
Pode estar usando LIBs no Clipper sem equivalente em xHarbour, então este vai ser o primeiro ponto a verificar.

2. Pode converter xharbour sem sair do clipper
Basta alterar sua linha de compilação do clipper, acrescentando o /n
E a partir daí, iniciar as modificações.

3. Cada módulo tem que ter seu nome dentro do fonte.
DIGITA.PRG
@ 1, 1 get texto

Isso vai ser alterado para
DIGITA.PRG
Procedure Digita // ou Function Digita()
@ 1, 1 get texto

A única exceção é o programa principal.
Obrigatoriamente, o nome tem que ser MAIN.
PRINCIPAL.PRG
Function Main()

Nessa primeira alteração, se tomar cuidado, pode usar o próprio xharbour pra ajudar, ou se seus fontes tiverem menos de 64kb, o próprio clipper. Assim só precisa mexer a mão o fonte principal. É apenas um esboço, confirme antes de colocar em prática sobrescrevendo os fontes originais.

mDirFiles := Directory("*.prg")
For nCont = 1 To Len(mDirFiles)
mNomePrg := mDirFiles[nCont,1]
mNomeInterno := Substr(mNomePrg,1,At(".",mNomePrg)-1) // primeira parte é o nome
mFontePrg = memoread(mNomePrg)
MemoWrit(mNomePrg,"procedure " + mNomeInterno + Chr(13) + Chr(10) + mFontePrg)
Next

Pronto.
Se usa só clipper padrão, o programa já deverá ser compilado tanto no Clipper quanto no xHarbour.
A partir daqui começarão algumas diferenças, mas mesmo assim ainda será possível usar nos dois.
Uma delas é quanto a nomes abreviados: comece a eliminar as abreviações
Tem também maiúsculas/minúsculas, ou detalhes simples, que algumas linhas no programa principal resolvem.
Nesta parte, acrescente
#ifdef __HARBOUR__
comandos diferentes
#endif
Pronto. Seu fonte continuará sendo o mesmo em Clipper e xharbour, e no programa principal, só essas linhas acima.
Pode escolher pra compilar com Clipper ou xHarbour a qualquer momento, sem mexer em nada.

De um modo geral, isso será suficiente pra ver o funcionamento lado a lado da versão Clipper e xHarbour.
Mas tudo depende do que usa a mais além do Clipper, e também do estilo do seu fonte.
Ainda vai encontrar algumas pequenas diferenças entre Clipper e xHarbour nesta fase.

Como estará usando o mesmo fonte, verá o mesmo resultado.
E vai estar ajustando tudo no ambiente clipper, o que vai tirar dúvidas sobre estar fazendo certo, e até evitar ter duas versões de fonte pra mexer.

Aqui nem uso xHarbour, mas o fonte continua podendo ser compilado nos dois, mesmo após anos de modificações.
É só fazer essas mudanças básicas, e manter o padrão.

Lógico... isso é só pra testar, ou pra uma mudança rápida a qualquer momento, mantendo os fontes sempre atualizados para Clipper/xHarbour.
Se decidir por xHarbour seria só usar, se decidir por não xHarbour, pelo menos organizou seus fontes Clipper e deixou prontos para uma decisão futura.

Sim.. ia esquecendo...
Do mesmo modo que no Clipper configura PATH para EXE, Includes e LIBs, também precisa configurar para o xHarbour e para o compilador C. De um modo geral, o hbmake atende a compilação, desde que estejam configurados esses PATHs.

PROGRAMAÇÃO: Clipper DOS ERROR 4 (000027-1/11/2009)

O Windows tem um limite padrão de arquivos abertos para programas DOS.
O limite padrão pode ser 20 ou 40, dependendo da versão do Windows.
Basta alterar este limite, aumentando para pelo menos 200 arquivos.
Esta configuração é definida pelo arquivo CONFIG.NT, na linhas FILES=200
No caso do JPA, no momento 200 é um limite mais que suficiente.

Caso utilize outro programa Clipper, que não seja o JPA, será necessário fazer outra alteração.
Em propriedades de meu computador, variáveis de ambiente, acrescente
SET CLIPPER=F200

PROGRAMAÇÃO: Clipper geração do TXT para Nota Fiscal Eletrônica NF-e (000021-1/4/2008)

Apenas pra ajuda a outros programadores
Caso seja feito em Clipper, o Clipper costuma acrescentar um Control-Z no final dos arquivos gerados, e este caractere deve ser removido.
O caractere fica visível no bloco de notas, e pode ser removido por ele, nos testes.
Em Clipper resolvi com esta rotina:

Function DelCtrZ(mFileName)
mHandle := fOpen(mFileName,FO_READWRITE)
FSeek(mHandle, -3, FS_END)
fWrite(mHandle, " ")
fClose(mHandle)
End Function


Obs. Ela não remove o Ctrl-Z, mas move para um local aonde o programa da Fazenda o despreza.

PROGRAMAÇÃO: Clipper Lentidão no Windows (000028-1/1/2000)

Isso NÃO atinge o JPA.
Muitos programadores Clipper não atualizaram seus programas, e no modo original o programa Clipper sobrecarrega o Windows.
Isso se deve ao fato de um programa DOS ficar sempre testando o teclado, pra ver se algo está sendo digitado.
Para a versão DOS/Clipper nos utilizamos da OSLIB, que contém funções para não sobrecarregar o Windows.
Com o programa Clipper carregado, olhe no gerenciador de tarefas, e verifique o consumo de CPU.
No JPA esse consumo é mínimo.
Em programas DOS não atualizados, o consumo fica em 100%, sobrecarregando o Windows, e causando superaquecimento da CPU.
Em programas Windows isso também pode acontecer, mas é mais difícil, já que as linguagens se encarregam de incluir recursos para contornar esse problema.

PROGRAMAÇÃO: Clipper demora para liberar relatório (000007-1/1/2000)

Isto NÃO atinge o sistema JPA.
Se estiver usando um programa DOS, e a impressão demorar para ser liberada, faça o seguinte:
Iniciar, executar, SYSEDIT
No arquivo SYSTEM.INI você encontra a seçao [386Enh]
Acrescente abaixo dela, caso não exista, as seguintes linhas
[Network]
PrintBufTime=1
[IFSMGR]
PrintBufTime=1

Isso vai fazer com que a impressão seja liberada em no máximo um segundo.

PROGRAMAÇÃO: Clipper Instalação Configurando impressora em rede Windows 2000 (000004-1/1/2000)

Obs. No JPA, isto se aplica somente se não estiver usando o Preview Windows

Em uma rede W2000 é necessário "capturar" a porta de impressora.
Pra isso, acrescentar ao BAT de carga do sistema, o seguinte:
NET USE LPT1: /delete
NET USE LPT1: servidorimpressora


Detalhes do(s) comando(s):
/delete
Para o caso de existir algum comando anterior ativado
servidor
Corresponde ao computador aonde a impressora está instalada, e deve ser obtida no próprio computador aonde a impressora está instalada.
Uma opção é entrar em Propriedades, de Meu Computador, e olhar o nome do computador.
impressora
Corresponde ao nome da impressora como ela foi compartilhada.
Uma opção é entrar em Propriedades, da Impressora, Compartilhamento, e verificar o nome com o qual a impressora foi compartilhada.
Também deve estar selecionado para compartilhar a impressora, caso contrário, ela não ficará disponível para as outras estações.
*** Dependendo de como estiver configurada a rede, pode ser necessário acrescentar um nome de usuário pra liberar o acesso à impressora
*** Caso o sistema esteja instalado em pasta não compatível com MsDos, serão apresentados problemas na impressão (Ex.pasta "Meus Documentos" não é permitido, mas "MEUSDOCS" é permitido).