Advpl o Manual
Advpl o Manual
Advpl o Manual
Versão 1.0
Índice
A Tecnologia Protheus...........................................................................................................17
Características da Tecnologia Protheus .............................................................................17
As Camadas do Advanced Protheus ...................................................................................17
Servidor de Aplicação ........................................................................................................18
Terminal Thin-Client...........................................................................................................18
Dados ....................................................................................................................................18
Repositório de Apo’s ..........................................................................................................18
Estruturação.............................................................................................................................19
A estrutura de diretórios do Advanced Protheus.........................................................19
Versão AP5.......................................................................................................................19
Versão AP6.......................................................................................................................19
Aplicativos do Advanced Protheus ..................................................................................20
Protheus Server ..............................................................................................................20
Remote .............................................................................................................................20
IDE.....................................................................................................................................20
Monitor..............................................................................................................................20
Nomenclaturas Utilizadas..................................................................................................21
Topologia de Rede..................................................................................................................21
Características e Possibilidades de Topologias de Rede............................................21
IDE - Integrated Development Environment....................................................................23
Características do IDE .......................................................................................................23
Monitor......................................................................................................................................24
Informações Básicas das Conexões................................................................................24
Btrieve .......................................................................................................................................24
Informações Básicas ..........................................................................................................24
Configuração do Btrieve/PervasiveSQL2000:...............................................................25
CTree .........................................................................................................................................27
Informações Básicas ..........................................................................................................27
Índices...................................................................................................................................27
Sistemas Operacionais e Plataformas (versão AP6 e posteriores) ..............................28
Sistemas Operacionais e Plataformas ............................................................................28
Plataformas e SO's suportados....................................................................................28
Novos SO's a serem suportados .................................................................................28
AdPl – Guia de Programação................................................................................................29
A Linguagem AdvPl.................................................................................................................29
Programação Com Interface Própria com o Usuário ..................................................29
Programação Sem Interface Própria com o Usuário ..................................................29
Programação por Processos.........................................................................................30
Programação de RPC.....................................................................................................30
Programação Web..........................................................................................................30
Programação TelNet ......................................................................................................30
Sintaxe da Linguagem ...........................................................................................................30
Edição de Programas .............................................................................................................30
Criação de um Programa ......................................................................................................30
Linhas de Programa ...........................................................................................................31
Linhas de Comando .......................................................................................................31
Linhas de Comentário....................................................................................................31
Linhas Mistas ...................................................................................................................32
Tamanho da Linha..............................................................................................................32
Estrutura de um Programa ...................................................................................................32
A Área de Identificação .....................................................................................................33
A Área de Ajustes Iniciais .................................................................................................33
O Corpo do Programa........................................................................................................34
A Área de Encerramento...................................................................................................34
Variáveis de Memória.............................................................................................................34
Tipos de Dados........................................................................................................................34
Numérico ..............................................................................................................................34
Lógico ....................................................................................................................................35
Caracter ................................................................................................................................35
Data .......................................................................................................................................35
Matriz (Array) ......................................................................................................................35
Bloco de Código ..................................................................................................................35
Criação e Atribuição de Variáveis........................................................................................36
Matrizes.....................................................................................................................................38
Matrizes como Estruturas .................................................................................................39
Cuidados com Matrizes......................................................................................................41
Inicializando Matrizes.............................................................................................................41
Se o tamanho da matriz é conhecido.............................................................................41
Se o tamanho da matriz não é conhecido ....................................................................42
Blocos de Código.....................................................................................................................42
Um Primeiro Lembrete ......................................................................................................42
Outro Lembrete...................................................................................................................43
Lista de Expressões............................................................................................................44
Duas Linhas de Código..................................................................................................44
Duas Linha de Código em Uma , Utilizando Ponto-e-Vírgula ...............................44
Convertendo para uma Lista de Expressões ............................................................44
Onde Pode-se Utilizar uma Lista de Expressões?....................................................45
De Listas de Expressões para Blocos de Código .........................................................45
Executando um Bloco de Código ................................................................................46
Passando Parâmetros ....................................................................................................47
Utilizando Blocos de Código .........................................................................................47
Escopo de Variáveis................................................................................................................48
Utilização de Identação.....................................................................................................72
Utilização de Espaços em Branco....................................................................................73
Quebra de Linhas Muito Longas......................................................................................73
Capitulação de Palavras-Chave .......................................................................................74
Utilização da Notação Húngara .......................................................................................74
Utilização de Nomes Significantes para Variáveis .......................................................74
Utilização de Comentários ................................................................................................74
Criação de Mensagens Sistêmicas Significantes e Consistentes ..............................75
Evitar Abreviação de Comandos em 4 letras................................................................75
Evitar "Disfarces" no Código ............................................................................................75
Evitar Código de Segurança Desnecessário..................................................................76
Isolamento de Strings de Texto ......................................................................................77
Tabela de Pictures de Formatação .....................................................................................77
Comando SAY/PSAY...........................................................................................................77
Comando GET......................................................................................................................77
Programação do AdvPl para o ERP Siga Advanced Protheus .......................................78
Prefácio .....................................................................................................................................78
O Que é Fazer um Programa com Inteligência............................................................79
Programando Simples, mas Certo...................................................................................80
Erros que Podem ser Evitados.........................................................................................80
A Importância de Programas Documentados...............................................................81
Cabeçalho de Programa / Função...................................................................................81
Criação de Variáveis...............................................................................................................82
A Declaração........................................................................................................................82
O Tipo de Variável..............................................................................................................82
Tipos Existentes ..............................................................................................................82
Inicialização..........................................................................................................................83
Padronização de Variáveis ................................................................................................83
Criando uma Variável Utilizando a Função CRIAVAR() ..............................................83
Variáveis de Relatórios ......................................................................................................84
Cuidados com o Posicionamento de Registros.................................................................85
Função Posicione ................................................................................................................86
Função Existcpo ..................................................................................................................86
Restaurando Índice e limpando filtros ...........................................................................86
Outros Cuidados......................................................................................................................87
Confrontando relatórios e consultas...............................................................................87
Problemas com Looping de Programas .........................................................................87
Manipulação de Arquivos Externos ao Protheus..........................................................88
Desenvolvendo Telas .........................................................................................................89
Salvando Array’s padrões .................................................................................................90
Pontos de Entrada ..................................................................................................................90
Objetivo dos Pontos de Entrada......................................................................................90
Quando criar um Ponto de Entrada................................................................................90
Sintaxe para criar um Ponto de Entrada:..................................................................91
ACopy ......................................................................................................................................140
AClone .....................................................................................................................................141
ADel .........................................................................................................................................142
ADir ..........................................................................................................................................142
AEval........................................................................................................................................143
AFill ..........................................................................................................................................145
AIns..........................................................................................................................................146
Alias..........................................................................................................................................146
Append From .........................................................................................................................147
Array ........................................................................................................................................149
AScan.......................................................................................................................................150
ASize ........................................................................................................................................152
ASort........................................................................................................................................153
ATail .........................................................................................................................................154
BTVCanOpen..........................................................................................................................154
BTVCreateDDFs.....................................................................................................................155
BTVDropIdxs..........................................................................................................................156
BTVTables...............................................................................................................................157
CDow .......................................................................................................................................158
CMonth....................................................................................................................................158
Commit....................................................................................................................................159
Copy To...................................................................................................................................160
Copy File .................................................................................................................................161
Copy Structure.......................................................................................................................162
CPYS2T....................................................................................................................................163
CPYT2S....................................................................................................................................164
CTreeDelIdxs .........................................................................................................................164
CTreeDellnt ............................................................................................................................165
CurDir ......................................................................................................................................166
Date .........................................................................................................................................167
Day...........................................................................................................................................167
DBAppend...............................................................................................................................168
DBClearAllFilter......................................................................................................................169
DBClearFilter ..........................................................................................................................170
DBCloseAll...............................................................................................................................170
DBCloseArea...........................................................................................................................171
DBClearIndex.........................................................................................................................171
DBCommit...............................................................................................................................172
DBCommitAll ..........................................................................................................................172
DBCreate.................................................................................................................................173
DBCreateIndex ......................................................................................................................174
DBDelete.................................................................................................................................175
DBEval .....................................................................................................................................175
DBF...........................................................................................................................................177
DBFieldInfo.............................................................................................................................177
DBFilter....................................................................................................................................178
DBGoBottom ..........................................................................................................................179
DBGoTo...................................................................................................................................180
DBGoTop.................................................................................................................................180
DBInfo .....................................................................................................................................181
DBOrderInfo...........................................................................................................................182
DBOrderNickName................................................................................................................183
DBRecall..................................................................................................................................184
DBRecordInfo ........................................................................................................................184
DBReindex ..............................................................................................................................185
DBRLock..................................................................................................................................186
DBRLockList ...........................................................................................................................187
DBRunLock .............................................................................................................................187
DbSeek....................................................................................................................................188
DBSetDriver............................................................................................................................190
DBSetFilter..............................................................................................................................190
DBSetIndex ............................................................................................................................191
DBSetNickName ....................................................................................................................192
DBSetOrder ............................................................................................................................193
DBSkip .....................................................................................................................................194
DBStruct..................................................................................................................................195
DBUnlock ................................................................................................................................195
DBUnlockAll ............................................................................................................................196
Delete ......................................................................................................................................196
Deleted....................................................................................................................................198
DevOutPict..............................................................................................................................198
DevPos ....................................................................................................................................199
Directory .................................................................................................................................200
DirRemove..............................................................................................................................201
DiskSpace ...............................................................................................................................202
Dow..........................................................................................................................................202
Dtoc..........................................................................................................................................203
Dtos..........................................................................................................................................204
Eject.........................................................................................................................................205
ElapTime .................................................................................................................................205
FClose ......................................................................................................................................206
FCreate....................................................................................................................................207
FErase......................................................................................................................................208
FError.......................................................................................................................................209
FieldBlock................................................................................................................................210
FieldWbl ..................................................................................................................................211
File............................................................................................................................................212
FOpen ......................................................................................................................................213
FOpenPort...............................................................................................................................214
FRead.......................................................................................................................................216
FReadStr .................................................................................................................................217
Frename..................................................................................................................................218
FSeek.......................................................................................................................................219
FWrite ......................................................................................................................................220
GetImpWindows....................................................................................................................222
GetPortActive .........................................................................................................................222
GetClientDir ............................................................................................................................223
Header.....................................................................................................................................223
IndexKey.................................................................................................................................224
IndexOrd.................................................................................................................................225
InitPrint ...................................................................................................................................225
IsPrinter ..................................................................................................................................226
IsCisaSyncOn .........................................................................................................................227
Locate......................................................................................................................................227
LUpdate...................................................................................................................................229
MakeDir...................................................................................................................................229
MemoLine ...............................................................................................................................230
MemoRead..............................................................................................................................231
MemoWrite .............................................................................................................................232
MLCount..................................................................................................................................232
Month ......................................................................................................................................233
MsCompress...........................................................................................................................234
MsCRC32.................................................................................................................................235
MsCRC32Str............................................................................................................................236
MsDecomp..............................................................................................................................236
OrdCondSet............................................................................................................................237
OrdCreate ...............................................................................................................................238
OrdDescend............................................................................................................................240
OrdKey ....................................................................................................................................241
OrdListAdd..............................................................................................................................242
PRow........................................................................................................................................243
Pack .........................................................................................................................................244
PCol..........................................................................................................................................244
PreparePrint ...........................................................................................................................245
PrnFlush ..................................................................................................................................246
RDDSetDefault.......................................................................................................................247
RealRDD..................................................................................................................................247
Recall .......................................................................................................................................248
RecSize....................................................................................................................................249
ReIndex...................................................................................................................................250
Replace....................................................................................................................................250
RLock.......................................................................................................................................252
Seconds...................................................................................................................................253
Seek .........................................................................................................................................253
Select.......................................................................................................................................254
Set Filter..................................................................................................................................255
Set Index ................................................................................................................................256
Set Order ................................................................................................................................257
SetPrc ......................................................................................................................................258
Skip ..........................................................................................................................................258
SplitPath..................................................................................................................................260
TCConType.............................................................................................................................261
TCDelFile.................................................................................................................................262
TCGenQry ...............................................................................................................................262
TCIsvLock ...............................................................................................................................263
TCRefresh ...............................................................................................................................263
TCSetBuff................................................................................................................................264
TCSetConn..............................................................................................................................264
TCSetDummy.........................................................................................................................265
TCSetField...............................................................................................................................266
TCSpExec................................................................................................................................267
TCSpExist................................................................................................................................268
TCSqlError ..............................................................................................................................269
TCSrvType ..............................................................................................................................269
TCSysExe ................................................................................................................................270
;TCUnLink ...............................................................................................................................271
TCVUnLock .............................................................................................................................271
TCVLock ..................................................................................................................................272
Time.........................................................................................................................................273
UnLock.....................................................................................................................................274
UpdateIntName.....................................................................................................................274
Use ...........................................................................................................................................275
Used.........................................................................................................................................277
Year..........................................................................................................................................277
ZAP...........................................................................................................................................278
Classes de Interface Visual.................................................................................................279
tSrvObject...............................................................................................................................279
Características ...................................................................................................................279
Propriedades ......................................................................................................................279
Métodos ..............................................................................................................................280
SetFocus .........................................................................................................................280
Hide .................................................................................................................................280
Show................................................................................................................................280
Enable .............................................................................................................................280
Disable ............................................................................................................................281
Refresh............................................................................................................................281
10
11
Metodos ..............................................................................................................................292
New..................................................................................................................................292
Exemplo ..............................................................................................................................293
tCheckBox...............................................................................................................................293
Hierarquia...........................................................................................................................293
Descrição ............................................................................................................................293
Métodos ..............................................................................................................................293
New..................................................................................................................................293
Exemplo ..............................................................................................................................294
tComboBox.............................................................................................................................295
Hierarquia...........................................................................................................................295
Descrição ............................................................................................................................295
Propriedades ......................................................................................................................295
Métodos ..............................................................................................................................295
New..................................................................................................................................295
Select...............................................................................................................................296
Exemplo ..............................................................................................................................297
tGet ..........................................................................................................................................297
Hierarquia...........................................................................................................................297
Descrição ............................................................................................................................297
Propriedades ......................................................................................................................297
Métodos ..............................................................................................................................298
New..................................................................................................................................298
Exemplo ..............................................................................................................................299
tGroup .....................................................................................................................................299
Hierarquia...........................................................................................................................299
Descrição ............................................................................................................................300
Métodos ..............................................................................................................................300
New..................................................................................................................................300
Exemplo ..............................................................................................................................300
tListbox....................................................................................................................................301
Hierarquia...........................................................................................................................301
Descrição ............................................................................................................................301
Parâmetros.........................................................................................................................301
Métodos ..............................................................................................................................301
New..................................................................................................................................301
Select...............................................................................................................................302
Add...................................................................................................................................303
Modify .............................................................................................................................303
Del....................................................................................................................................303
Len ...................................................................................................................................304
Reset ...............................................................................................................................304
Exemplo ..............................................................................................................................304
tMeter ......................................................................................................................................305
12
Hierarquia...........................................................................................................................305
Descrição ............................................................................................................................305
Parâmetros.........................................................................................................................305
Métodos ..............................................................................................................................305
New..................................................................................................................................305
Set....................................................................................................................................306
Exemplo ..............................................................................................................................306
tMultiget..................................................................................................................................307
Hierarquia...........................................................................................................................307
Descrição ............................................................................................................................307
Propriedades ......................................................................................................................307
Métodos ..............................................................................................................................308
New..................................................................................................................................308
EnableVScroll.................................................................................................................309
EnableHScroll.................................................................................................................309
Exemplo ..............................................................................................................................310
tPanel.......................................................................................................................................310
Hierarquia...........................................................................................................................310
Descrição ............................................................................................................................310
Métodos ..............................................................................................................................310
New..................................................................................................................................310
Exemplo ..............................................................................................................................311
tRadMenu ...............................................................................................................................311
Hierarquia...........................................................................................................................311
Descrição ............................................................................................................................311
Propriedades ......................................................................................................................312
Métodos ..............................................................................................................................312
New..................................................................................................................................312
EnableItem.....................................................................................................................313
Exemplo ..............................................................................................................................313
tSay..........................................................................................................................................313
Hierarquia...........................................................................................................................313
Descrição ............................................................................................................................314
Parâmetros.........................................................................................................................314
Métodos ..............................................................................................................................314
New..................................................................................................................................314
SetText............................................................................................................................315
Exemplo ..............................................................................................................................315
tScrollbox ................................................................................................................................316
Hierarquia...........................................................................................................................316
Descrição ............................................................................................................................316
Métodos ..............................................................................................................................316
New..................................................................................................................................316
Exemplo ..............................................................................................................................316
13
Infra-estrutura.......................................................................................................................318
MsGetDados ...........................................................................................................................318
MsGetDb .................................................................................................................................322
MsmGet...................................................................................................................................326
MBrowse .................................................................................................................................329
Funções...................................................................................................................................330
AllGroups.................................................................................................................................330
AllUsers ...................................................................................................................................331
APMsgAlert .............................................................................................................................333
APMsgInfo ..............................................................................................................................333
APMsgNoYes ..........................................................................................................................334
APMsgStop..............................................................................................................................334
APMsgYesNo ..........................................................................................................................335
APMsgYesNo ..........................................................................................................................335
Cabec.......................................................................................................................................336
Capital .....................................................................................................................................338
CloseBrowse...........................................................................................................................338
Conpad1..................................................................................................................................339
Enchoicebar............................................................................................................................339
FileNoExt.................................................................................................................................340
Final .........................................................................................................................................341
FTPConnect ............................................................................................................................341
FTPDirChange........................................................................................................................342
FTPDirectory ..........................................................................................................................343
FTPDisconnect.......................................................................................................................343
FTPDownload.........................................................................................................................344
FTPErase.................................................................................................................................344
FTPGetCurDir .........................................................................................................................345
FTPRenameFile......................................................................................................................345
FTPUpload ..............................................................................................................................346
FunDesc ..................................................................................................................................347
FunName ................................................................................................................................347
GetCountryList.......................................................................................................................348
GetMark...................................................................................................................................348
GetMv ......................................................................................................................................349
IncProc ....................................................................................................................................350
IncRegua.................................................................................................................................350
IndRegua ................................................................................................................................352
MarkBRefresh.........................................................................................................................353
MarkBrow................................................................................................................................353
Ms_Flush.................................................................................................................................354
MsAppend...............................................................................................................................356
MsCopyFile .............................................................................................................................356
MsCopyTo ...............................................................................................................................357
14
MsCreate.................................................................................................................................358
MsErase...................................................................................................................................358
MsFile.......................................................................................................................................359
MsRename..............................................................................................................................360
MsUnlock.................................................................................................................................360
OurSpool .................................................................................................................................361
Pergunte .................................................................................................................................362
Processa..................................................................................................................................363
ProcRegua ..............................................................................................................................364
PswAdmin ...............................................................................................................................364
PswID ......................................................................................................................................365
PswName ................................................................................................................................365
PswOrder ................................................................................................................................366
PswRet.....................................................................................................................................367
PswSeek..................................................................................................................................367
ReadVar...................................................................................................................................368
RetAcsName...........................................................................................................................368
RetExtHlp ................................................................................................................................369
RetExtHls ................................................................................................................................369
RetExtHpr ...............................................................................................................................370
RetExtMnu ..............................................................................................................................370
RetFileName...........................................................................................................................371
Roda.........................................................................................................................................371
RptStatus ................................................................................................................................373
SetDefault...............................................................................................................................374
SetPrint....................................................................................................................................376
SetRegua ................................................................................................................................378
SixDescricao...........................................................................................................................380
VerSenha ................................................................................................................................380
X1Def01 ..................................................................................................................................381
X1Def02 ..................................................................................................................................381
X1Def03 ..................................................................................................................................382
X1Def04 ..................................................................................................................................382
X1Def05 ..................................................................................................................................383
X1Pergunt...............................................................................................................................383
X2Nome...................................................................................................................................384
X3CBox....................................................................................................................................385
X3Descric ................................................................................................................................385
X3Picture.................................................................................................................................386
X3Titulo...................................................................................................................................386
X3Uso ......................................................................................................................................386
X5Descri ..................................................................................................................................387
X6Conteud..............................................................................................................................388
X6Desc1 ..................................................................................................................................388
15
X6Desc2 ..................................................................................................................................389
X6Descric ................................................................................................................................389
XADescric................................................................................................................................390
XBDescri..................................................................................................................................390
16
O Advanced Protheus é uma nova tecnologia desenvolvida sobre o sistema Advanced, que teve toda a
inteligência dividida em duas camadas: Servidor de Aplicação (Protheus Server) e Interface (Remote). Ou
seja, uma aplicação 32 bits que se encarrega do gerenciamento das conexões, da execução do código
AdvPl e do acesso aos recursos de banco de dados (ADS, Btrieve, CTree ou TopConnect), e uma aplicação
thin-client que efetua apenas a interface com o usuário.
1.Em disco
2.Via Windows
3.Direto na Porta
As impressões efetuadas via Windows ou diretamente na porta podem ser impressas no servidor (o
que evitará o tráfego de rede do relatório impresso) ou na estação. As impressões efetuadas em disco
também evitam o tráfego de rede. Os relatórios em disco são sempre mantidos no servidor e somente
as páginas requisitadas são enviadas à estação.
• Não existe o conceito de "módulos" de sistema. Existe o conceito de programa inicial, de onde a
execução do Remote será iniciada (e os outros APO's utilizados serão carregados e descarregados
dinamicamente de acordo com sua chamada a partir deste). Isso permite que rotinas que eram de
"módulos" diferentes sejam executadas diretamente de um mesmo menu de usuário
17
• Servidor de Aplicação
• Terminal Thin-Client
• Dados
• Repositório de APO´s
O Remote é a aplicação encarregada da interface com o usuário. Não existe processamento local, por isso
o tráfego de rede entre o Terminal e o Servidor de Aplicação é baixo, tratando-se apenas de comandos
para o desenho das telas e do tratamento do teclado e mouse.
Dados
O acesso aos dados é efetuado pelo Servidor de Aplicação utilizando as seguintes bases de dados: ADS,
BTrieve, CTree e TopConnect (para padrão SQL). Para bases de dados SQL, existe total suporte a Stored
Procedures. No Protheus, todas as bases de dados têm suporte a controle de transação.
E no repositório que se encontram os programas escritos em AdvPl que serão carregados para a execução
de determinada tarefa. É através do repositório de Apo’s que pode-se incluir novas customizações no
sistema.
18
Est r u t uração
Versão AP5
\ap5\ Diretório inicial do Protheus. É a partir deste diretório que o sistema irá localizar os
caminhos informados em parâmetros, customizações, etc.
\ap5\relato\ Similar ao \RELATO\ das versões Advanced 2.0x/4.0x. Diretório para gravação de
arquivos de impressão em disco.
\ap5\cprova\ Similar ao \CPROVA\ das versões Advanced 2.0x/4.0x. Diretório para gravação de
arquivos de contabilização.
Versão AP6
\ap6\ Diretório inicial do Protheus. É a partir deste diretório que o sistema irá localizar os
caminhos informados em parâmetros, customizações, etc.
\ap6\bin\remote\ Diretório onde são localizados os arquivos das aplicações clientes (Remote, IDE,
Monitor, etc): executáveis, bibliotecas de carga dinâmica (DLL´s) e arquivos de
19
configuração.
\ap6\relato\ Similar ao \RELATO\ das versões Advanced 2.0x/4.0x. Diretório para gravação de
arquivos de impressão em disco.
\ap6\cprova\ Similar ao \CPROVA\ das versões Advanced 2.0x/4.0x. Diretório para gravação de
arquivos de contabilização.
Estas são as estruturas para uma instalação padrão do Protheus de acordo com a versão utilizada.
Porém a localização de instalação pode variar de acordo com o local de instalação.
O Advanced Protheus possui, basicamente, quatro aplicativos utilizados com diferentes finalidades. São
eles:
Protheus Server
Trata-se do servidor de aplicação do Advanced Protheus esta é a parte do sistema que será executada no
Servidor e será responsável pela comunicação entre o Cliente, a Base de Dados e o Repositório de Apo’s.
O nome do executável depende da versão e sistema operacional utilizados, por exemplo: AP5SRV.EXE ou
AP6SRVWIN.EXE.
Remo te
É o Remote que utilizamos para interagir com todo o sistema, ele poderá ser instalado de duas maneiras,
no servidor ou na própria estação de trabalho. O nome do executável depende da versão utilizada, por
exemplo: AP5RMT.EXE ou AP6RMT.EXE.
I DE
Trata-se do ambiente de desenvolvimento integrado do Advanced Protheus. É através deste aplicativo que
todos os acessos aos repositórios de Apo’s (compilação de customizações, visualização de funções
existentes etc.) são efetuados, e também é a ferramenta para desenvolvimento e depuração de
aplicações/customizações. O nome do executável depende da versão utilizada, por exemplo: AP5IDE.EXE
ou AP6IDE.EXE.
Moni tor
20
Esta ferramenta permite a interação com os usuários conectados ao sistema: Analisar os programas em
uso, derrubar conexões pendentes, enviar mensagens ao usuários etc. O nome do executável depende da
versão utilizada, por exemplo: AP5MONIT.EXE ou AP6MONIT.EXE
Alem destas aplicações, o Siga Advanced Protheus conta ainda com outros utilitários diversos, como o Diff
(utilizado para comparação de arquivos texto) e Dump (utilizado para edição de arquivos binários).
B u i l d: Versão completa do sistema com seus executáveis, Dll’s e RPO completo. O build do sistema pode
ser identificado através da opção Miscelâneas | Sobre dentro dos módulos do sistema.
Ve rs ã o Ma s t e r: Mesma definição de build porém neste caso a versão será utilizada como referência para
a geração de atualizações do sistema (patch’s). Quando gerada, a versão é encaminhada a todos os
envolvidos em processos de implantação/utilização do sistema via correio ou disponibilizada no site de FTP
do Protheus.
A definição dos nomes dos arquivos dos repositórios de APO's e Patch´s seguem o mesmo padrão
(diferenciando-se apenas na extensão Patch=.PAT e repositório=RPO) e é efetuada da seguinte
maneira AP12345.RPO:
3 – Versão;
4 – Versão;
5 – Versão;
Por exemplo, APBP609.RPO será um repositório de APO's para base de dados BTrieve, idioma
Português e versão 609.
Topologia de Rede
Devido à sua divisão em camadas, a tecnologia Protheus permite montar o ambiente de execução com
diferentes topologias, priorizando a execução, o tráfego de rede ou os recursos individuais das máquinas
existentes, o que torna o processamento distribuído. Essa é uma das grandes vantagens da tecnologia
Protheus.
21
• Um Protheus Server pode estar na mesma máquina que o gerenciador de banco de dados.
• Máquinas melhores ou com mais recursos podem ter um Protheus Server sendo executado
localmente (na estação) visando priorizar o processamento local. Porém há um aumento do tráfego
de rede entre o gerenciador de banco de dados e o Protheus Server local.
• Utilização do protocolo TCP-IP para as conexões. Na versão AP5 pode-se utilizar também o
protocolo NAMED PIPES.
• Pode-se disponibilizar conexões via Internet através da montagem de um Web Server na empresa
ou através de provedores de acesso (como a UOL e o ZAZ). Neste caso, o Protheus Server pode ser
executado no provedor ou na empresa utilizando uma LP para a conexão ao provedor de acesso.
• A Internet é utilizada apenas como o meio de comunicação, ou seja, a conexão TCP-IP entre o
Remote e o Protheus Server. Além da segurança oferecida pelo sistema Advanced, a segurança
deverá ser oferecida pela conexão. Por isso, é aconselhável que a máquina onde o servidor Web
esteja sendo executado não seja o mesmo do servidor da banco de dados.
• O Protheus Server também pode ser executado como um servidor Internet, HTTP e/ou FTP.
• Pode-se manter uma página para o download do Remote, de modo que os usuário remotos possam
efetuar o download para conectar-se e utilizar o sistema. Na versão AP6 pode-se configurar o
Remote para se atualizar automaticamente a partir do Protheus Server sendo executado como um
servidor FTP.
22
Como ferramenta de edição e depuração, engloba todos os recursos disponíveis nas melhores ferramentas
de desenvolvimento do mercado.
Característ icas do I DE
• Para a execução do IDE não é necessário conectar-se ao Protheus Server, exceto nas operações de
atualização ou consulta de um repositório (compilação, obtenção do Mapa de Objetos, aplicação de
patch´s, etc) e durante o processo de depuração.
• Não é aconselhável executar o IDE remotamente (via Internet ou via modem), pois a conexão do
Remote ao Protheus, quando efetuada através do IDE, é mais lenta.
4.D e p u r aç ã o. O IDE permite aos usuários depurar as rotinas criadas, executando-as linha a linha ou
em modo de animação. Permite visualizar informações como variáveis em diferentes escopos,
pilha de chamadas, lista de break points, etc. Exatamente como as melhores ferramentas de
desenvolvimento existentes no mercado. No IDE pode-se depurar pontos de entrada
simplesmente colocando-se um ponto de parada (break point) em uma linha qualquer do código
do ponto de entrada;
23
Monitor
O Monitor é utilizado para monitorar as conexões de terminais ao Protheus Server. Através dele pode-se:
• Desabilitar novas conexões. Isto é útil quando se precisa efetuar alguma manutenção e se precisa
evitar que outros usuários se conectem.
• Usuário. É o nome do usuário na rede local. Para conexões remotas este nome está em branco.
• Tempo de Uso. Indica o tempo em horas, minutos e segundos desde que o Remote se conectou.
• Programa Inicial. É o nome do programa inicial (APO) com o qual o Remote iniciou a execução.
Bt rieve
I nf or mações Básicas
• Para programar algo específico para o Btrieve pode-se utilizar o teste "#ifdef BTV";
• As manipulações e visualizações de dados devem ser feitas através do "APSdu", pois as antigas
ferramentas são incompatíveis;
• O Btrieve versão 6.15 não precisa ser instalado, pois as DLLs necessárias são disponibilizadas junto
com o Protheus. Os arquivos necessários ficam no diretório "BIN" (wbtrv32.dll, w32mkrc.dll,
wbtrvres.dll e w32mkde.exe). O funcionamento é praticamente igual ao Btrieve Server, portanto
pode-se executar os testes na versão 6.15 normalmente;
• O w32mkde continua um período em execução após o término do Protheus, pois se o Protheus for
executado novamente não é necessário seu reinício. Quando o usuário desejar renomear o diretório
24
"BIN", o mesmo não será permitido por esse motivo, deve-se portanto finalizar a execução do
mesmo;
• As informações das tabelas, campos e índices são armazenados no diretório "DDF", criado abaixo do
"RootPath", através dos arquivos (Field.btv, File.btv, Finfo.btv, Iinfo.btv e Index.btv). Se estes
arquivos forem apagados as tabelas serão recriadas e todos os dados serão PERDIDOS. Não se pode
copiar uma tabela com estrutura diferente para este diretório, pois seus dados devem ser
atualizados nos arquivos do DDF também. Como os dados e o diretório DDF devem estar
"sincronisados" os arquivos do DDF devem ser incluídos no esquema de "backup" dos dados;
• As tabelas só podem ter "um" campo do tipo memo e este campo deve ser o último, por isso na
hora da criação da tabela o Protheus automaticamente desloca o campo memo para o final e mostra
uma mensagem de aviso;
• Para apagar os índices, entrar em APSdu, abrir a tabela e escolher Index/erase all. Ele apagará
todos os índices da tabela e também a sua definição no DDF. Para fazer via programa, selecione a
tabela e chame a função <@>BTVDropIdxs(). Portanto aconselha-se utilizar o índice do tipo
permanente somente se o mesmo for utilizado posteriormente (outras aberturas da tabela) caso
contrário deve-se utilizar os índices temporários;
• Para gerar os arquivos DFF´s compatíveis com outras ferramentas que manipulam arquivos btrieve,
inclusive Crystal Reports, existem duas funções para criar os arquivos necessários: <@>BTVTables e
<@>BTVCreateDDFs;
4.Entrar no Pervasive Control Center (menu Iniciar - Pervasive - Pervasive Control Center);
5.Visualizar os nomes dos servidores disponíveis (no caso de Linux, Novell e Solaris deve-se
acrescentar um servidor);
6.Através de um duplo click sobre o servidor que se deseja utilizar entrar em "configuração"
(configuration);
Pasta Access:
• MaxDatabases: 10
• Number of Sessions: 20
Pasta Communication Buffer Size:
25
• System Cache: On
Pasta Performance Tunning:
• Communications Threads : 64
A versão 6.15 possui uma limitação: Se dois servidores NT4 estiverem acessando o mesmo
arquivo, ocorrerá lentidão na rede. Isso acontece se for utilizado o mesmo RPO (que é um arquivo
btrieve) para dois servidores no AP5. A solução é sempre replicar os repositórios em cada servidor
ou adquirir (deve ser comprado) a versão a partir da PervasiveSQL2000. Em máquinas Win2000,
não é nem mesmo possível abrir um arquivo btrieve de dois servidores. Este problema é de
conhecimento da Pervasive, mas não será alterado porque esta versão foi descontinuada por volta
de agosto de 2001.
26
CTree
I nf or mações Básicas
• Para programar algo específico para o Ctree pode-se utilizar o teste “#ifdef CTREE”;
• A extensão padrão das tabelas é “.dtc”. Quando o LocalFile estiver utilizando o banco Ctree os SXs
continuam tendo como padrão a extensão “.dbf”, mas as tabelas criadas (SX1990.DBF, SX2990.DBF,
etc) são Ctree. Portanto recomenda-se que se configure outra extensão padrão para arquivos locais
do tipo Ctree através da chave “LocalDbExtension” no arquivo “ap6srv.ini” como “.dtc”;
• As manipulações e visualizações de dados devem ser feitas através do “APSdu”, pois as antigas
ferramentas são incompatíveis;
• O Ctree não precisa ser instalado, pois sua biblioteca é gerada junto com o Protheus;
• Os campos do tipo memo devem ser os últimos da tabela, por isso na hora da sua criação o
Protheus automaticamente desloca-os para o final e mostra uma mensagem de aviso;
• As tabelas geradas pelo Ctree são totalmente compatíveis entre as plataformas Windows e Linux,
pode-se inclusive copiar uma tabela gerada no Linux e abrí-la no Windows e vice-e-versa.
Í ndices
• - O índice interno do Ctree (ordem do recno) é criado em outro arquivo com extensão “.int”. Uma
pasta (“ctreeint”) é criada abaixo da pasta com a tabela. Nesta pasta serão armazenados todos os
índices internos daquele diretório. Caso não exista o arquivo de índice interno o mesmo é gerado
automaticamente pelo Protheus mostrando um aviso de que reconstruiu o índice no servidor na hora
da abertura da tabela. Para apagá-lo pode ser utilizada uma função <@>CTREEDELINT;
• - Os arquivos de índices permanentes são criados fora do arquivo da tabela com extensão padrão
como nos outros RDDs (“.cdx”), mas suas informações são armazenadas no arquivo da tabela
(“.dtc”). Portanto para se criar ou excluir índices permanentes a tabela deve estar aberta em modo
exclusivo. Na hora da abertura da tabela, todos os arquivos de índices permanentes relacionados em
sua estrutura são abertos também, por isso não se pode deletar o arquivo de índice permanente com
a respectiva tabela aberta. Caso não exista um ou mais arquivos de índices da tabela na hora de sua
abertura, o Protheus irá recriá-los automaticamente de forma semelhante ao índice interno. O
diretório do arquivo de índice também é armazenado na estrutura da tabela, mas quando a tabela é
aberta e é constatado que a tabela está em outro diretório o Protheus automaticamente atualiza esta
informação. Para se deletar os índices de uma tabela Ctree pode-se utilizar a função
<@>CTREEDELIDXS ou utilizar a opção “Index/erase all” no APSdu. Portanto aconselha-se utilizar o
índice do tipo permanente somente se o mesmo for utilizado posteriormente (outras aberturas da
tabela) caso contrário deve-se utilizar os índices temporários;
27
O Protheus Server foi desenvolvido em ANSI C++ e , portanto, independe de API's especificas para
funcionar. Graças a isso, o núcleo do Protheus pode ser recompilado em todos os sistemas operacionais e
plataformas que suportem ANSI C++.
Outra preocupação durante o desenvolvimento do Protheus foi garantir total compatibilidade dos
repositórios de objetos do Protheus (RPO's) e das correções dos repositórios (Patch's) entre os sistemas
operacionais e plataformas.
• Windows IA64,
• HP UX ( RISC ),
• PocketPC
28
A Linguagem AdvPl
A Linguagem AdvPl teve seu início em 1994, sendo na verdade uma evolução na utilização de linguagens
no padrão xBase pela Microsiga Software S.A. (Clipper, Visual Objects e depois FiveWin). Com a criação
da tecnologia Protheus, era necessário criar uma linguagem que suportasse o padrão xBase para a
manutenção de todo o código existente do sistema de ERP Siga Advanced. Foi então criada a linguagem
chamada Advanced Prot heus Lang uage.
O AdvPl é uma extensão do padrão xBase de comandos e funções, operadores, estruturas de controle de
fluxo e palavras reservadas, contando também com funções e comandos disponibilizados pela Microsiga
que a torna uma linguagem completa para a criação de aplicações ERP prontas para a Internet. Também é
uma linguagem orientada a objetos e eventos, permitindo ao programador desenvolver aplicações visuais
e criar suas próprias classes de objetos.
Quando compilados, todos os arquivos de código tornam-se unidades de inteligência básicas, chamados
APO´s (de Advanced Protheus Objects). Tais APO´s são mantidos em um repositório e carregados
dinamicamente pelo AP6 Server para a execução. Como não existe a linkedição, ou união física do código
compilado a um determinado módulo ou aplicação, funções criadas em AdvPl podem ser executadas em
qualquer ponto do ambiente Advanced Protheus.
O compilador e o interpretador da linguagem AdvPl é o próprio servidor AP6 (AP6 Server), e existe um
ambiente visual para desenvolvimento integrado (AP6 IDE) onde o código pode ser criado, compilado e
depurado.
Os programas em AdvPl podem conter comandos ou funções de interface com o usuário. De acordo com
tal característica, tais programas são subdivididos nas seguintes categorias:
Nesta categoria entram os programas desenvolvidos para serem executados através do terminal remoto
do Protheus, o AP6 Remote. O AP6 Remote é a aplicação encarregada da interface e da interação com o
usuário, sendo que todo o processamento do código em AdvPl, o acesso ao banco de dados e o
gerenciamento de conexões é efetuado no AP6 Server. O AP6 Remote é o principal meio de acesso a
execução de rotinas escritas em AdvPl no AP6 Server, e por isso permite executar qualquer tipo de código,
tenha ele interface com o usuário ou não. Porém nesta categoria são considerados apenas os programas
que realizem algum tipo de interface remota utilizando o protocolo de comunicação do Protheus.
Pode-se criar rotinas para a customização do sistema ERP Advanced Protheus, desde processos adicionais
até mesmo relatórios. A grande vantagem é aproveitar todo o ambiente montado pelos módulos do ERP
Advanced Protheus. Porém, com o AdvPl é possível até mesmo criar toda uma aplicação, ou módulo, do
começo.
As rotinas criadas sem interface são consideradas nesta categoria porque geralmente têm uma utilização
mais específica do que um processo adicional ou um relatório novo. Tais rotinas não têm interface com o
usuãrio através do AP6 Remote, e qualquer tentativa nesse sentido (como a criação de uma janela
padrão) ocasionará uma exceção em tempo de execução. Estas rotinas são apenas processos, ou Jobs,
executados no AP6 Server. Algumas vezes, a interface destas rotinas fica a cargo de aplicações externas,
29
desenvolvidas em outras linguagens, que são responsáveis por iniciar os processos no servidor AP6
através dos meios disponíveis de integração e conectividade no Protheus.
De acordo com a utilização e com o meio de conectividade utilizado, estas rotinas são subcategorizadas
assim:
Rotinas escritas em AdvPl podem ser iniciadas como processos individuais (sem interface) no AP6 Server
através de duas maneiras: Iniciadas por outra rotina AdvPl através da chamada de funções como StartJob
ou CallProc ou iniciadas automaticamente na inicialização do AP6 Server (quando propriamente
configurado).
Programação de RPC
Através de uma biblioteca de funções disponível no Protheus (uma API de comunicação), pode-se executar
rotinas escritas em AdvPl diretamente no AP6 Server, através de aplicações externas escritas em outras
linguagens. Isto é o que se chama de RPC (de Remote Procedu re Call, ou Cha mada de Procedi mentos
Re mota).
O servidor Protheus também pode executar rotinas em AdvPl em outros servidores Protheus através de
conexão TCP/IP direta utilizando o conceito de RPC. Do mesmo modo, aplicações externas podem
requisitar a execução de rotinas escritas em AdvPl através de conexão TCP/IP direta.
Programação Web
O AP6 Server pode também ser executado como um servidor Web, respondendo a requisições HTTP. No
momento destas requisições, pode executar rotinas escritas em AdvPl como processos individuais,
enviando o resultado das funções como retorno das requisições para o cliente HTTP (como por exemplo
um Browser de Internet). Qualquer rotina escrita em AdvPl que não contenha comandos de interface pode
ser executada através de requisições HTTP. O Protheus permite a compilação de arquivos HTML contendo
código AdvPl embutido. São os chamados arquivos AdvPl ASP, para a criação de páginas dinâmicas.
Programação TelNe t
TelNet é parte da gama de protocolos TCP/IP que permite a conexão a um computador remoto através de
uma aplicação cliente deste protocolo. O AP6 Server pode emular um terminal TelNet, através da
execução de rotinas escritas em AdvPl. Ou seja, pode-se escrever rotinas AdvPl cuja interface final será
um terminal TelNet ou um coletor de dados móvel.
Edição de Programas
Criação de um Programa
30
Um programa de computador nada mais é do que um grupo de comandos logicamente dispostos com o
objetivo de executar determinada tarefa. Esses comandos são gravados em um arquivo texto que é
transformado em uma linguagem executável por um computador através de um processo chamado
co mpilação. A compilação substitui os comandos de alto nível (que os humanos compreendem) por
instruções de baixo nível (compreendida pelo sistema operacional em execução no computador). No caso
do AdvPl, não é o sistema operacional de um computador que irá executar o código compilado, mas sim o
AP6 Server.
Dentro de um programa, os comandos e funções utilizados devem seguir regras de sintaxe da linguagem
utilizada, pois caso contrário o programa será interrompido por erros. Os erros podem ser de compilação
ou de execução.
Erros de compilação são aqueles encontrados na sintaxe que não permitem que o arquivo de código do
programa seja compilado. Podem ser comandos especificados de forma errônea, utilização inválida de
operadores, etc.
Erros de execução são aqueles que acontecem depois da compilação, quando o programa está sendo
executado. Podem ocorrer por inúmeras razões, mas geralmente se referem a funções não existentes, ou
variáveis não criadas ou inicializadas, etc.
Linhas de Programa
As linhas existentes dentro de um arquivo texto de código de programa podem ser linhas de comando,
linhas de comentário ou linhas mistas.
Linhas de Co mando
Linhas de comando possuem os comandos ou instruções que serão executadas. Por exemplo:
Local nCnt
Local nSoma := 0
For nCnt := 1 To 10
nSoma += nCnt
Next nCnt
Linhas de comentário possuem um texto qualquer, mas não são executadas. Servem apenas para
documentação e para tornar mais fácil o entendimento do programa. Existem três formas de se comentar
linhas de texto. A primeira delas é utilizar o sinal de * (asterisco) no começo da linha:
Todas as linhas iniciadas com um sinal de asterisco são consideradas como comentário. Pode-se utilizar a
palavra NOTE ou dois símbolos da letra "e" comercial (&&) para realizar a função do sinal de asterisco.
Porém todas estas formas de comentário de linhas são obsoletas e existem apenas para compatibilização
com o padrão xBase. A melhor maneira de comentar linhas em AdvPl é utilizar duas barras transversais:
31
Outra forma de documentar textos é utilizar as barras transversais juntamente com o asterisco, podendo-
se comentar todo um bloco de texto sem precisar comentar linha a linha:
/*
Programa para cálculo do total
Autor: Microsiga Software S.A.
Data: 2 de outubro de 2001
*/
Todo o texto encontrado entre a abertura (indicada pelos caracteres /*) e o fechamento (indicada pelos
caracteres */) é considerado como comentário.
Linhas Mistas
O AdvPl também permite que existam linhas de comando com comentário. Isto é possível incluíndo-se as
duas barras transversais (//) ao final da linha de comando e adicionando-se o texto do comentário:
Local nCnt
Local nSoma := 0 // Inicializa a variável com zero para a soma
For nCnt := 1 To 10
nSoma += nCnt
Next nCnt
Tamanho da Linha
Assim como a linha física, delimitada pela quantidade de caracteres que pode ser digitado no editor de
textos utilizado, existe uma linha considerada linha lógica. A linha lógica, é aquela considerada para a
compilação como uma única linha de comando.
A princípio, cada linha digitada no arquivo texto é diferenciada após o pressionamento da tecla <Enter>.
Ou seja, a linha lógica, é a linha física no arquivo. Porém algumas vezes, por limitação física do editor de
texto ou por estética, pode-se "quebrar" a linha lógica em mais de uma linha física no arquivo texto. Isto
é efetuado utilizando-se o sinal de ponto-e-vírgula (;).
GravaDados(cNome,cEnd,cTel,cFax,cEmail)
Endif
Neste exemplo existe uma linha de comando para a checagem das variáveis utilizadas. Como a linha
torna-se muito grande, pode-se dividí-la em mais de uma linha física utilizando o sinal de ponto-e-vírgula.
Se um sinal de ponto-e-vírgula for esquecido nas duas primeiras linhas, durante a execução do programa
ocorrerá um erro, pois a segunda linha física será considerada como uma segunda linha de comando na
compilação. E durante a execução esta linha não terá sentido.
32
Apesar de não ser uma linguagem de padrões rígidos com relação à estrutura do programa, é importante
identificar algumas de suas partes. Considere o programa de exemplo abaixo:
/*
+===========================================+0
| Programa: Cálculo do Fatorial |
| Autor : Microsiga Software S.A. |
| Data : 02 de outubro de 2001 |
+===========================================+
*/
Local nCnt
Local nResultado := 1 // Resultado do fatorial
Local nFator := 5 // Número para o cálculo
// Cálculo do fatorial
For nCnt := nFator To 1 Step -1
nResultado *= nCnt
Next nCnt
// Termina o programa
Return
1.Área de Identificação
3.Corpo do Programa
4.Área de Encerramento
Esta é uma área que não é obrigatória e é dedicada a documentação do programa. Quando existente,
contém apenas comentários explicando a sua finalidade, data de criação, autor, etc, e aparece no começo
do programa, antes de qualquer linha de comando.
O formato para esta área não é definido. Pode-se colocar qualquer tipo de informação desejada e escolher
a formatação apropriada.
/*
+==========================================+
| Programa: Cálculo do Fatorial |
| Autor : Microsiga Software S.A. |
| Data : 02 de outubro de 2001 |
+==========================================+
*/
Opcionalmente pode-se incluir definições de constantes utilizadas no programa ou inclusão de arquivos de
cabeçalho nesta área.
33
Nesta área geralmente se fazem os ajustes iniciais, importantes para o correto funcionamento do
programa. Entre os ajustes se encontram declarações de variáveis, inicializações, abertura de arquivos,
etc. Apesar do AdvPl não ser uma linguagem rígida e as variáveis poderem ser declaradas em qualquer
lugar do programa, é aconselhável fazê-lo nesta área visando tornar o código mais legível e facilitar a
identificação de variáveis não utilizadas.
Local nCnt
Local nResultado := 0 // Resultado do fatorial
Local nFator := 10 // Número para o cálculo
O Corpo do Programa
É nesta área que se encontram as linhas de código do programa. É onde se realiza a tarefa necessária
através da organização lógica destas linhas de comando. Espera-se que as linhas de comando estejam
organizadas de tal modo que no final desta área o resultado esperado seja obtido, seja ele armazenado
em um arquivo ou em variáveis de memória, pronto para ser exibido ao usuário através de um relatório
ou na tela.
// Cálculo do fatorial
For nCnt := nFator To 1 Step -1
nResultado *= nCnt
Next nCnt
A Área de Encerramen to
É nesta área onde as finalizações são efetuadas. É onde os arquivos abertos são fechados, e o resultado
da execução do programa é utilizado. Pode-se exibir o resultado armazenado em uma variável ou em um
arquivo ou simplesmente finalizar, caso a tarefa já tenha sido toda completada no corpo do programa. É
nesta área que se encontra o encerramento do programa. Todo programa em AdvPl deve sempre terminar
com a palavra chave return.
// Termina o programa
Return
Variáveis de Memória
Tipos de Dados
O AdvPl não é uma linguagem de tipos rígidos (strongly typed), o que significa que variáveis de memória
podem diferentes tipos de dados durante a execução do programa. Variáveis podem também conter
objetos, mas os tipos primários da linguagem são:
Numérico
34
O AdvPl não diferencia valores inteiros de valores com ponto flutuante, portanto pode-se criar variáveis
numéricas com qualquer valor dentro do intervalo permitido. Os seguintes elementos são do tipo de dado
numérico:
2
43.53
0.5
0.00001
1000000
Uma variável do tipo de dado numérico pode conter um número de dezoito dígitos incluindo o ponto
flutuante, no intervalo de 2.2250738585072014 E–308 até 1.7976931348623158 E+308.
Lógico
Valores lógicos em AdvPl são identificados através de .T. ou .Y. para verdadeiro e .F. ou .N. para falso
(independentemente se os caracteres estiverem em maiúsculo ou minúsculo).
Caracter
Strings ou cadeias de caracteres são identificadas em AdvPl por blocos de texto entre aspas duplas (") ou
aspas simples ('):
"Olá mundo!"
'Esta é uma string'
"Esta é 'outra' string"
Uma variável do tipo caracter pode conter strings com no máximo 1 Mb, ou seja, 1048576 caracteres.
Data
O AdvPl tem um tipo de dados específico para datas. Internamente as variáveis deste tipo de dado são
armazenadas como um número correspondente a data Juliana.
Variáveis do tipo de dados Data não podem ser declaradas diretamente, e sim através da utilização de
funções específicas como por exemplo ctod que converte uma string para data.
Mat r iz (Array)
Matrizes são um tipo de dado especial. É a disposição de outros elementos em colunas e linhas. O AdvPl
suporta matrizes uni ou multidimensionais. Os elementos de uma matriz são acessados através de índices
numéricos iniciados em 1, identificando a linha e coluna para quantas dimenões existirem.
Uma matriz pode conter no máximo 100000 elementos, independentemente do número de dimensões.
Matrizes devem ser utilizadas com cautela, pois se forem muito grandes podem exaurir a memória do
servidor.
Bloco de Código
O bloco de código é um tipo de dado especial. É utilizado para armazenar instruções escritas em AdvPl
que poderão ser executadas posteriormente.
35
A partir do momento que uma variável é criada, não é necessário mais se referenciar ao seu conteúdo, e
sim ao seu nome. O nome de uma variável é um identificador único que segue duas regras regras:
Má x i m o d e 1 0 c a r a c t e r es. O AdvPl não impede a criação de uma variável de memória cujo nome
contenha mais de 10 caracteres, porém apenas os 10 primeiros serão considerados para a localização do
conteúdo armazenado. Portanto se forem criadas duas variáveis cujos 10 primeiros caracteres forem
iguais, como nTotalGeralAnual e nTotalGeralMensal, as referências a qualquer uma delas no programa
resultarão o mesmo. Ou seja, serão a mesma variável:
nTotalGeralMensal := 100
nTotalGeralAnual := 300
Alert("Valor mensal: " + cValToChar(nTotalGeralMensal))
Quando o conteúdo da variável nTotalGeralMensal é exibido, o seu valor será de 300. Isso acontece
porque no momento que esse valor foi atribuido à variável nTotalGeralAnual, o AdvPl considerou apenas
os 10 primeiros caracteres (assim como o faz quando deve exibir o valor da variável nTotalGeralMensal),
ou seja, considerou-as como a mesma variável. Assim o valor original de 100 foi substituido pelo de 300.
O AdvPl permite a criação ilimitada de variáveis, dependendo apenas da memória disponível. A seguir
estão alguns nomes válidos para variáveis:
TOT01
cNumero
VAR_QUALQUER
M_CARGO
A11
E alguns inválidos:
O AdvPl não é uma linguagem de tipos rígidos para variáveis, ou seja, não é necessário informar o tipo de
dados que determinada variável irá conter no momento de sua declaração, e o seu valor pode mudar
durante a execução do programa. Também não há necessidade de declarar variáveis em uma seção
específica do seu código fonte, embora seja aconselhável declarar todas as variáveis necessárias no
começo, tornando a manutenção mais fácil e evitando a declaração de variáveis desnecessárias.
Para declarar uma variável deve-se utilizar um identificador de escopo, seguido de uma lista de variáveis
separadas por vírgula (,). Um identificador de escopo é uma palavra chave que indica a que contexto do
programa a variável declarada pertence. O contexto de variáveis pode ser local (visualizadas apenas
36
dentro do programa atual), público (visualizadas por qualquer outro programa), entre outros. Os
diferentes tipos de contexto de variáveis são explicados na documentação sobre escopo de variáveis.
Se esta linha for executada em um programa AdvPl, ocorrerá um erro de execução com a mensagem
"variable does not exist: nPercentual", pois esta variável está sendo utilizada em uma expressão de
cálculo sem ter sido declarada. Para solucionar este erro, deve-se declarar a variável previamente:
Neste exemplo, as variáveis são declaradas previamente utilizando o identificador de escopo local. Quando
a linha de cálculo for executada, o erro de variável não existente não mais ocorrerá. Porém variáveis não
inicializadas têm sempre o valor default nulo (Nil) e este valor não pode ser utilizado em um cálculo pois
também gerará erros de execução (nulo não pode ser dividido por 100). A resolução deste problema é
efetuada inicializando-se a variável através de uma das formas:
Local nPercentual,nResultado
Store 10 To nPercentual
nResultado := 250 * (1 + (nPercentual / 100))
ou
ou
A diferença entre o último exemplo e os dois anteriores é que a variável é inicializada no momento da
declaração. Nos dois primeiros exemplos, a variável é primeiro declarada e então inicializada em uma
outra linha de código. O comando store existe apenas por compatibilidade com versões anteriores e outras
linguagens xBase, mas é obsoleto. Deve-se utilizar o operador de atribuição (:= ou somente =). É
aconselhável optar pelo operador de atribuição composto de dois pontos e sinal de igual, pois o operador
de atribuição utilizando somente o sinal de igual pode ser facilmente confundido com o operador relacional
(para comparação) durante a criação do programa.
Uma vez que um valor lhe seja atribuído, o tipo de dado de uma variável é igual ao tipo de dado do valor
atribuído. Ou seja, uma variável passa a ser numérica se um número lhe é atribuído, passa a ser caracter
se uma string de texto lhe for atribuída, etc. Porém mesmo que uma variável seja de determinado tipo de
dado, pode-se mudar o tipo da variável atribuindo outro tipo a ela:
37
02
03 xVariavel := "Agora a variável é caracter..."
04 Alert("Valor do Texto: " + xVariavel)
05
06 xVariavel := 22 // Agora a variável é numérica
07 Alert(cValToChar(xVariavel))
08
09 xVariavel := .T. // Agora a variável é lógica
10 If xVariavel
11 Alert("A variável tem valor verdadeiro...")
12 Else
13 Alert("A variável tem valor falso...")
14 Endif
15
16 xVariavel := Date() // Agora a variável é data
17 Alert("Hoje é: " + DtoC(xVariavel))
18
19 xVariavel := nil // Nulo novamente
20 Alert("Valor nulo: " + xVariavel)
21
22 Return
No programa de exemplo anterior, a variável xVariavel é utilizada para armazenar diversos tipos de
dados. A letra "x" em minúsculo no começo do nome é utilizada para indicar uma variável que pode conter
diversos tipos de dados, segundo a Notação Húngara (consulte documentação específica para detalhes).
Este programa troca os valores da variável e exibe seu conteúdo para o usuário através da função alert.
Essa função recebe um parâmetro que deve ser do tipo string de caracter, por isso dependendo do tipo de
dado da variável xVariavel é necessário fazer uma conversão antes.
Apesar dessa flexibilidade de utilização de variáveis, deve-se tomar cuidados na passagem de parâmetros
para funções ou comandos, e na concatenação (ou soma) de valores. Note a linha 20 do programa de
exemplo. Quando esta linha é executada, a variável xVariavel contem o valor nulo. A tentativa de soma de
tipos de dados diferentes gera erro de execução do programa. Nesta linha do exemplo, ocorrerá um erro
com a mensagem "type mismatch on +". Excetuando-se o caso do valor nulo, para os demais deve-se
sempre utilizar funções de conversão quando necessita-se concatenar tipos de dados diferentes (por
exemplo, nas linhas 07 e 17.
Note também que quando uma variável é do tipo de dado lógico, ela pode ser utilizada diretamente para
checagem (linha 10):
If xVariavel
é o mesmo que
If xVariavel = .T.
A declaração de variáveis para os demais tipos de dados, matrizes e blocos de código, é exatamente igual
ao descrito até agora. Apenas existem algumas diferenças quanto a inicialização, que podem ser
consultadas na documentação de inicialização de matrizes e blocos de código.
Mat rizes
38
Matrizes, ou arrays, são coleções de valores. Ou, de uma maneira mais fácil de entender, uma lista. Uma
matriz pode ser criada através de diferentes maneiras. Consulte a documentação sobre Inicialização de
Matrizes para maiores detalhes.
Cada item em uma matriz é referenciado pela indicação de sua posição numérica na lista, iniciando pelo
número 1. O exemplo a seguir declara uma variável, atribui uma matriz de três elementos a ela, e então
exibe um dos elementos e o tamanho da matriz:
O AdvPl permite a manipulação de matrizes facilmente. Enquanto que em outras linguagens como C ou
Pascal é necessário alocar memória para cada elemento de uma matriz (o que tornaria a utilização de
"pointeiros" necessária), o AdvPl se encarrega de gerenciar a memória e torna simples adicionar
elementos a uma matriz, utilizando a função aAdd:
Uma característica interessante do AdvPl é que uma matriz pode conter qualquer coisa: números, datas,
lógicos, caracteres, objetos, etc. E ao mesmo tempo. Em outras palavras, os elementos de uma matriz
não precisam ser necessariamente do mesmo tipo de dado, em contraste com outras linguagens como C e
Pascal.
aFunct1 := {"Pedro",32,.T.}
Esta matriz contem uma string, um número e um valor lógico. Em outras linguagens como C ou Pascal,
este "pacote" de informações pode ser chamado como um "struct" (estrutura em C, por exemplo) ou um
"record" (registro em Pascal, por exemplo). Como se fosse na verdade um registro de um banco de dados,
um pacote de informações construído com diversos campos. Cada campo tendo um pedaço diferente de
dado.
Suponha que no exemplo anterior, o array aFunct1 contenha informações sobre o nome de uma pessoa,
sua idade e sua situação matrimonial. Os seguintes #defines podem ser criados para indicar cada posição
dos valores dentro da matriz:
#define FUNCT_NOME 1
#define FUNCT_IDADE 2
#define FUNCT_CASADO 3
39
Alert(aFunct1[FUNCT_NOME])
Alert(aFunct2[FUNCT_NOME])
Alert(aFunct3[FUNCT_NOME])
Agora, ao invés de trabalhar com variáveis individuais, pode-se agrupá-las em uma outra matriz, do
mesmo modo que muitos registros são agrupados em uma tabela de banco de dados:
aFuncts é uma matriz com 3 linhas por 3 colunas. Uma vez que as variáveis separadas foram combinadas
em uma matriz, os nomes podem ser exibidos assim:
Local nCount
Alert(aFuncts[nCount,FUNCT_NOME])
// aFuncts[nCount][FUNCT_NOME]
Next nCount
40
A variável nCount seleciona que funcionário (ou que linha) é de interesse. Então a constante
FUNCT_NOME seleciona a primeira coluna daquela linha.
Matrizes são listas de elementos, portanto memória é necessária para armazenar estas informações.
Como as matrizes podem ser multidimensionais, a memória necessária será a multiplicação do número de
itens em cada dimensão da matriz, considerando-se o tamanho do conteúdo de cada elemento contido
nesta. Portanto o tamanho de uma matriz pode variar muito.
A facilidade da utilização de matrizes, mesmo que para armazenar informações em pacotes como descrito
anteriormente, não é compensada pela utilização em memória quando o número de itens em um array for
muito grande. Quando o número de elementos for muito grande deve-se procurar outras soluções, como a
utilização de um arquivo de banco de dados temporário.
Não há limitação para o número de dimensões que uma matriz pode ter, mas o número de elementos
máximo (independentes das dimensões onde se encontram) é de 100000.
01 Local nCnt
02 Local aX[10]
03 Local aY := Array(10)
04 Local aZ := {0,0,0,0,0,0,0,0,0,0}
05
06 For nCnt := 1 To 10
08 Next nCnt
Este código preenche a matriz com uma tabela de quadrados. Os valores serão 1, 4, 9, 16 ... 81, 100.
Note que a linha 07 se refere à variável aX, mas poderia também trabalhar com aY ou aZ. O objetivo
deste exemplo é demonstrar trÊs modos de criar uma matriz de tamanho conhecido no momento da
criação do código.
Na linha 02 a matriz é criada usando aX[10]. Isto indica ao AdvPl para alocar espaço para 10 elementos
na matriz. Os colchetes [ e ] são utilizados para indicar o tamanho necessário.
Na linha 03 é utilizada a função array com o parâmetro 10 para criar a matriz, e o retorno desta função é
atribuído à variável aY.
41
Na linha 03 é efetuado o que se chama "desenhar a imagen da matriz". Como pode-se notar, existem dez
0´s na lista encerrada entre chaves ({}). Claramente, este método não é o utilizado para criar uma matriz
de 1000 elementos. O terceiro método difere dos anteriores porque inicializa a matriz com os valores
definitivos. Nos dois primeiros métodos, cada posição da matriz contém um valor nulo (Nil) e deve ser
inicializado posteriormente.
A linha 07 demonstra como um valor pode ser atribuído para uma posição existente em uma matriz
especificando o índice entre colchetes.
Se o tamanho da matriz não é conhecido até o momento da execução do programa, há algumas maneiras
de criar uma matriz e adicionar elementos a ela. O exemplo a seguir ilustra a idéia de criação de uma
matriz vazia (sem nenhum elemento) e adição de elementos dinamicamente.
01 Local nCnt
02 Local aX[0]
03 Local aY := Array(0)
04 Local aZ := {}
05
07 aAdd(aX,nCnt*nCnt)
08 Next nCnt
A linha 02 utiliza os colchetes para criar uma matriz vazia. Apesar de não ter nenhum elemento, seu tipo
de dado é matriz.
Na linha 03 a chamada da função array cria uma matriz sem nenhum elemento.
Na linha 04 está declarada a representação de uma matriz vazia em AdvPl. Mais uma vez, estão sendo
utilizadas as chaves para indicar que o tipo de dados da variável é matriz. Note que {} é uma matriz vazia
(tem o tamanho 0), enquanto {Nil} é uma matriz com um único elemento nulo (tem tamanho 1).
Porque cada uma destas matrizes não contem elementos, a linha 07 utiliza a função aadd para adicionar
elementos sucessivamente até o tamanho necessário (especificado por exemplo na variável nSize).
Blocos de Código
Blocos de código são um conceito existente há muito tempo em linguagens xBase. Não como algo que
apareceu da noite para o dia, e sim uma evolução progressiva utilizando a combinação de muitos
conceitos da linguagem para a sua implementação.
O AdvPl é uma linguagem baseada em funções. Funções têm um valor de retorno. Assim como o operador
de atribuição :=.
42
Posde-se escrever:
A expressão x:=10 é avaliada primeiro, e então seu resultado (o valor de X, que agora é 10) é passada
para a função cvaltochar para a conversão para caracter, e em seguida para a função alert para a
exibição. Por causa desta regra de precedência é possível atribuir um valor a mais de uma varíavel ao
mesmo tempo:
Z := Y := X := 0
Por causa dessa regra, essa expressão é avaliada como se fosse escrita assim:
Z := ( Y := (X := 0) )
Apesar do AdvPl avaliar expressões da esquerda para a direita, no caso de atribuições isso acontece ao
contrário, da direita para a esquerda. O valor é atribuído à variável X, que retorna o valor para ser
atribuído à variável Y e assim sucessivamente. Pode-se dizer que o zero foi "propagado através da
expressão".
Ou t ro Lem bre te
Em AdvPl pode-se juntar diversas linhas de código em uma única linha físcia do arquivo. Por exemplo, o
código:
If lAchou
Alert("Cliente encontrado!")
Endif
43
O ponto-e-vírgula indica ao AdvPl que a nova linha de código está para começar. Pode-se então colocar
diversas linhas lógicas de código na mesma linha física através do editor de texto utilizado.
Apesar da possibilidade de se escrever todo o programa assim, em uma única linha física, isto não é
recomendado pois dificulta a legibilidade do programa e, conseqüentemente, a manutenção.
Lista de Ex pressões
A evolução dos blocos de código começa com as listas de expressões. Nos exemplos a seguir, o símbolo
==> indicará o retorno da expressão após sua avaliação (seja para atribuir em uma variável, exibir para o
usuário ou imprimir em um relatório), que será impresso em um relatório por exemplo.
Cada uma das linhas terá a expressão avaliada, e o valor da variável será então impresso.
Este é o mesmo código que o anterior, apenas escrito em uma única linha:
Apesar desse código se encontrar em uma única linha física, existem duas linhas lógicas separadas pelo
ponto e vírgula. Ou seja, esse código é equivalente a:
Alert( cValToChar( x := 10 ) )
y := 20
Portanto apenas o valor 10 da variável x será passado para as funções cvaltochar e alert para ser exibido.
E o valor 20 apenas será atribuído à variável y.
Quando parênteses são colocados ao redor do código e o sinal de ponto-e-vírgula substituído por uma
vírgula apenas, o código torna-se uma lista de expressões:
O valor de retorno resultante de uma lista de expressões é o valor resultante da última expressão ou
elemento da lista. Funciona como se fosse um pequeno programa ou função, que retorna o resultado de
sua última avaliação (efetuadas da esquerda para a direita).
44
Neste exemplo, a expressão x := 10 é avaliada, e então a expressão y := 20, cujo valor resultante é
passado para a função alert e cvaltochar, e então exibido. Depois que essa linha de código é executada, o
valor de X é igual a 10 e o de y igual a 20, e 20 será exibido.
Teoricamente, não há limitação para o número de expressões que podem ser combinadas em uma lista de
expressões. Na prática, o número máximo é por volta de 500 símbolos.
Debugar listas de expressões é difícil oprque as expressões não estão divididas em linhas de código fonte,
o que torna todas as expressões associadas a uma mesma linha de código. Isto pode tornar muito difícil
determinar onde um erro ocorreu.
O propósito principal de uma lista de expressões é agrupá-las em uma única unidade. Em qualquer lugar
do código AdvPl que uma expressão simples pode ser utilizada, pode-se utilizar uma lista de expressões. E
ainda, pode-se fazer com que várias coisas aconteçam onde normalmente apenas uma aconteceria.
X := 10 ; Y := 20
If X > Y
Alert("X")
Z := 1
Else
Alert("Y")
Z := -1
Endif
Aqui temos o mesmo conceito, escrito utilizando listas de expressões na função iif:
X := 10 ; Y := 20
iif( X > Y , ;
( Alert("X"), Z := 1 ) , ;
( Alert("Y"), Z := -1 ) )
45
O AdvPl permite criar funções, que são pequenos pedaços de código, como se fosse um pequeno
programa, utilizados para diminuir partes de tarefas mais complexas e reaproveitar código em mais de um
lugar num programa. Para maiores detalhes consulte a documentação sobre a criação de funções em
AdvPl. Porém, a idéia neste momento é que a lista de expressões utilizada na linha anterior pode ser
criada como uma função:
Function Lista()
X := 10
Y := 20
Return Y
E a linha de exemplo com a lista de expressões pode ser substituída, tendo o mesmo resultado, por:
Como mencionado anteriormente, uma lista de expressões é como um pequeno programa ou função. Com
poucas mudanças, uma lista de expressões pode se tornar um bloco de código:
( X := 10 , Y := 20 ) // Lista de Expressões
Note as chaves {} utilizadas no bloco de código. Ou seja, um bloco de código é uma matriz. Porém na
verdade, não é uma lista de dados, e sim uma lista de comandos, uma lista de código.
Diferentemente de uma matriz, não se pode acessar elementos de um bloco de código através de um
índice numérico. Porém blocos de código são semelhantes a uma lista de expressões, e a uma pequena
função. Ou seja, podem ser executados. Para a execução, ou avaliação, de um bloco de código, deve-se
utilizar a função eval:
46
Essa função recebe como parâmero um bloco de código e avalias todas as expressões contidas neste bloco
de código, retornando o resultado da última expressão avaliada.
Já que blocos de código são como pequenas funções, também é possível a passagem de parâmetros para
um bloco de código. Os parâmetros devem ser informados entre as barras verticais (||) separados por
vírgulas, assim como em uma função.
B := {| N | X := 10, Y := 20 + N}
Porém deve-se notar que já que o bloco de código recebe um parâmetro, um valor deve ser passado
quando o bloco de código for avaliado.
C := Eval(B, 1) ==> 21
Blocos de código podem ser utilizados em diversas situações. Geralmente são utilizados para executar
tarefas quando eventos de objetos são acionados ou para modificar o comportamento padrão de algumas
funções.
Esta matriz pode ser ordenada pelo primeiro nome, utilizando-se a chamada da função asort(A), resultado
na matriz com os elementos ordenados dessa forma:
A ordem padrão para a função asort é ascendente. Este comportamento pode ser modificado através da
informação de um bloco de código que ordena a matriz de forma descendente:
B := { |X, Y| X > Y }
aSort(A, B)
O bloco de código (de acordo com a documentação da função asort) deve ser escrito para aceitar dois
parâmetros que são os dois elementos da matriz para comparação. Note que o bloco de código não
conhece que elementos está comparando - a função asort seleciona os elementos (talvez utilizando o
algorítmo QuickSor t) e passa-os para o bloco de código. O bloco de código compara-os e retorna
verdadeiro (.T.) se se encontram na ordem correta, ou falso (.F.) se não. Se o valor de retorno for falso, a
função asort irá então trocar os valores de lugar e seguir comparando o próximo par de valores.
47
Então, no bloco de código anterior, a comparação X > Y é verdadeira se os elementos estão em ordem
descendente, o que significa que o primeiro valor é maior que o segundo.
Para ordenar a mesma matriz pelo último nome, também em orden descendente, pode-se utilizar o
seguinte bloco de código:
Note que este bloco de código procura e compara as partes dos caracteres imediatamente seguinte a um
espaço em branco. Depois de utilizar esse bloco de código para a função asort, a matriz conterá:
Finalmente, para ordenar um sub-elemento (coluna) de uma matriz por exemplo, pode-se utilizar o
seguinte bloco de código:
Escopo de Variáveis
Local nNumero := 10
Esta linha de código declara uma variável chamada nNumero indicando que pertence seu escopo é local.
• LOCAL
• STATIC
48
• PRIVATE
• PUBLIC
nNumero2 := 15
Quando um valor é atribuído à uma variável em um programa ou função, o AdvPl criará a variável caso
ela não tenha sido declarada anteriormente. A variável então é criada como se tivesse sido declarada
como Private.
Devido a essa característica, quando pretende-se fazer uma atribuição a uma variável declarada
previamente mas escreve-se o nome da variável de forma incorreta, o AdvPl não gerará nenhum
erro de compilação ou de execução. Pois compreenderá o nome da variável escrito de forma
incorreta como se fosse a criação de uma nova variável. Isto alterará a lógica do programa, e é um
erro muitas vezes difícil de identificar.
Variáveis Locais
Variáveis locais são pertencentes apenas ao escopo da função onde foram declaradas. Devem ser
explicitamente declaradas com o identificador LOCAL, como no exemplo:
Function Pai()
<comandos>
Filha()
<mais comandos>
Return(.T.)
49
Neste exemplo, a variável nVar foi declarada como local e atribuída com o valor 10. Quando a função Filha
é executada, nVar ainda existe mas não pode ser acessada. Quando a execução da função Pai terminar, a
variável nVar é destruída. Qualquer variável com o mesmo nome no programa que chamou a função Pai
não é afetada.
Variáveis locais são criadas automaticamente cada vez que a função onde forem declaradas for ativada.
Elas continuam a existir e mantêm seu valor até o fim da ativação da função (ou seja, até que a função
retorne o controle para o código que a executou). Se uma função é chamada recursivamente (por
exemplo, chama a si mesma), cada chamada em recursão cria um novo conjunto de variáveis locais.
A visibilidade de variáveis locais é idêntica ao escopo de sua declaração. Ou seja, a variável é visível em
qualquer lugar do código fonte em que foi declarada. Se uma função é chamada recursivamente, apenas
as variáveis locais criadas na mais recente ativação são visíveis.
O escopo das variáveis estáticas depende de onde são declaradas. Se forem declaradas dentro do corpo
de uma função ou procedimento, seu escopo será limitado àquela rotina. Se forem declaradas fora do
corpo de qualquer rotina, seu escopo é todo o arquivo de programa.
Neste exemplo, a variável nVar é declarada como estática e inicializada com o valor 10:
Function Pai()
Static nVar := 10
<comandos>
Filha()
<mais comandos>
Return(.T.)
Quando a função Filha é executada, nVar ainda existe mas não pode ser acessada. Diferente de variáveis
declaras como LOCAL ou PRIVATE, nVar continua a existir e mantem seu valor atual quando a execução
da função Pai termina. Entretanto, somente pode ser acessada por execuções subseqüêntes da função Pai.
Variáveis Privadas
A declaração é opcional para variáveis privadas. Mas podem ser declaradas explicitamente com o
identificador PRIVATE.
50
Adicionalmente, a atribuição de valor a uma variável não criada anteriormente automaticamente cria a
variável como privada. Uma vez criada, uma variável privada continua a existir e mantem seu valor até
que o programa ou função onde foi criada termine (ou seja, até que a função onde foi criada retorne para
o código que a executou). Neste momento, é automaticamente destruída.
É possível criar uma nova variável privada com o mesmo nome de uma variável já existente. Entretanto, a
nova (duplicada) variável pode apenas ser criada em um nível de ativação inferior ao nível onde a variável
foi declarada pela primeira vez (ou seja, apenas em uma função chamada pela função onde a variável já
havia sido criada). A nova variável privada irá esconder qualquer outra variável privada ou pública (veja a
documentação sobre variáveis públicas) com o mesmo nome enquanto existir.
Uma vez criada, uma variável privada é visível em todo o programa enquanto não for destruída
automaticamente quando a rotina que a criou terminar ou uma outra variável privada com o mesmo nome
for criada em uma subfunção chamada (neste caso, a variável existente torna-se inacessível até que a
nova variável privada seja destruída).
Em termos mais simples, uma variável privada é visível dentro da função de criação e todas as funções
chamadas por esta, a menos que uma função chamada crie sua própria variável privada com o mesmo
nome.
Por exemplo:
Function Pai()
Private nVar := 10
<comandos>
Filha()
<mais comandos>
Return(.T.)
Neste exemplo, a variável nVar é criada como privada e inicializada com o valor 10. Quando a função Filha
é executada, nVar ainda existe e, diferente de uma variável local, pode ser acessada pela função Filha.
Quando a função Pai terminar, nVar será destruída e qualquer declaração de nVar anterior se tornará
acessível novamente.
Variáveis Públicas
Pode-se criar variáveis públicas dinamicamente no código com o identificador PUBLIC. As variáveis
públicas continuam a existir e mantêm seu valor até o fim da execução.
É possível criar uma variável privada com o mesmo nome de uma variável pública existente. Entretanto,
não é permitido criar uma variável pública com o mesmo nome de uma variável privada existente.
Uma vez criada, uma variável pública é visível em todo o programa onde foi declarada até que seja
escondida por uma variável privada criada com o mesmo nome. A nova variável privada criada esconde a
51
variável pública existente, e esta se tornará inacessível até que a nova variável privada seja destruída. Por
exemplo:
Function Pai()
Public nVar := 10
<comandos>
Filha()
<mais comandos>
Return(.T.)
Neste exemplo, nVar é criada como pública e inicializada com o valor 10. Quando a função Filha é
executada, nVar ainda existe e pode ser acessada. Diferente de variáveis locais ou privadas, nVar ainda
existe após o término da a execução da função Pai.
Diferentemente dos outros identificadores de escopo, quando uma variável é declarada como
pública sem ser inicializada, o valor assumido é falso (.F.) e não nulo (nil).
Para especificar qual deve ser o elemento referenciado, deve-se utilizar o operador de identificação de
apelido (->) e um dos dois identificadores de referência, MEMVAR ou FIELD.
cRes := MEMVAR->NOME
Esta linha de comando identifica que o valor atribuído à variável cRes deve ser o valor da variável de
memória chamada NOME.
cRes := FIELD->NOME
52
Neste caso, o valor atribuído à variável cRes será o valor do campo NOME existente no arquivo ou tabela
aberto na área atual.
O identificador FIELD pode ser substituído pelo apelido de um arquivo ou tabela aberto, para evitar a
necessidade de selecionar a área antes de acessar o conteúdo de terminado campo.
cRes := CLIENTES->NOME
Para maiores detalhes sobre abertura de arquivos com atribuição de apelidos, consulte a documentação
sobre acesso a banco de dados ou a documentação da função dbUseArea.
Operadores da Linguagem
Operadores Comuns
Na documentação sobre variáveis há uma breve demonstração de como atribuir valores a uma variável da
forma mais simples. O AdvPl amplia significativamente a utilização de variáveis através do uso de
expressões e funções. Uma expressão é um conjunto de operadores e operandos cujo resultado pode ser
atribuído a uma variável ou então analisado para a tomada de decisões. Por exemplo:
Neste exemplo são utilizadas algumas expressões para calcular o salário líquido após um aumento. Os
operandos de uma expressão podem ser uma variável, uma constante, um campo de arquivo ou uma
função.
+ Adição
- Subtração
* Multiplicação
53
/ Divisão
** ou ^ Exponenciação
Operadores de St r ing
- Concatenação de strings com eliminação dos brancos finais das strings intermediárias
Operadores Relacionais
= Comparação Igual
ou
ou
!=
Operadores Lógicos
.And. E lógico
.Or. OU lógico
54
Operadores de At ribuição
Os operadores utilizados em AdvPl para atribuição de valores a variáveis de memória são:
= Atribuição Simples
:= Atribuição em Linha
nVariavel = 10
At r ib uição em Linha
O operador de atribuição em linha é caracterizado por dois pontos e o sinal de igualdade. Tem a mesma
função do sinal de igualdade sozinho, porém aplia a atribuição às variáveis. Com ele pode-se atribuir mais
de uma variável ao mesmo tempo.
Quando diversas variáveis são inicializadas em uma mesma linha, a atribuição começa da direita para a
esquerda, ou seja, nVar3 recebe o valro zero inicialmente, nVar2 recebe o conteúdo de nVar3 e nVar1
recebe o conteúdo de nVar2 por final.
Com o operador de atribuição em linha, pode-se substituir as inicializações individuais de cada variável
por uma inicialização apenas:
55
por
O operador de atribuição em linha também pode ser utilizado para substituir valores de campos em um
banco de dados.
Os operadores de atribuição composta são uma facilidade da linguagem AdvPl para expressões de cálculo
e atribuição. Com eles pode-se economizar digitação:
+= X += Y X=X+Y
-= X -= Y X=X-Y
*= X *= Y X=X*Y
/= X /= Y X=X/Y
**= ou ^= X **= Y X = X ** Y
%= X %= Y X=X%Y
Os operadores de decremento/incremento podem ser colocados tanto antes (pré-fixado) como depois
(pós-fixado) do nome da variável. Dentro de uma expressão, a ordem do operador é muito importante,
podendo alterar o resultado da expressão. Os operadores incrementais são executados da esquerda para a
direita dentro de uma expressão.
Local nA := 10
56
Local nB := nA++ + nA
O valor da variável nB resulta em 21, pois a primeira referência a nA (antes do ++) continha o valor 10
que foi considerado e imediatamente aumentado em 1. Na segunda referência a nA, este já possuía o
valor 11. O que foi efetuado foi a soma de 10 mais 11, igual a 21. O resultado final após a execução
destas duas linhas é a variável nB contendo 21 e a variável nA contendo 11.
No entando:
Local nA := 10
Local nB := ++nA + nA
Resulta em 22, pois o operador incremental aumentou o valor da primeira nA antes que seu valor fosse
considerado.
Operadores Especiais
Além dos operadores comuns, o AdvPl possui alguns outros operadores ou identificadores. Estas são suas
finalidades:
() Agrupamento ou Função
[] Elemento de Matriz
& Macrosubstituição
Os parênteses são utilizados para agrupar elementos em uma expressão mudando a ordem de
precedência da avaliação da expressão (segundo as regras matemáticas por exemplo). Também servem
para envolver os argumentos de uma função. Veja a documentação sobre precedência de operadores
para maiores detalhes.
Os colchetes são utilizados para especificar um elemento específico de uma matriz. Por exemplo, A[3,2],
refere-se ao elemento da matriz A na linha 3, coluna 2.
As chaves são utilizadas para a especificação de matrizes literais ou blocos de código. Por exemplo,
A:={10,20,30} cria uma matriz chamada A com três elementos.
O símbolo -> identifica um campo de um arquivo diferenciando-o de uma variável. Por exemplo, FUNC-
>nome refere-se ao campo nome do arquivo FUNC. Mesmo que exista uma variável chamada nome, é o
campo nome que será acessado.
O símbolo & identifica uma avaliação de expressão através de macro e é visto em detalhes na
documentação sobre macrossubstituição.
57
O símbolo @ é utilizado para indicar que durante a passagem de uma variável para uma função ou
procedimento ela seja tomada como uma referência e não como valor.
2.Operadores de String
3.Operadores Matemáticos
4.Operadores Relacionais
5.Operadores Lógicos
6.Operadores de Atribuição
Em expressões complexas com diferentes tipos de operadores, a avaliação seguirá essa sequência. Caso
exista mais de um operador do mesmo tipo (ou seja, de mesmo nível), a avaliação se dá da esquerda
para direita. Para os operadores matemáticos entretanto há uma precedência a seguir:
1.Exponenciação
2.Multiplicação e Divisão
3.Adição e Subtração
Considere o exemplo:
O resultado desta expressão é 30, pois primeiramente é calculada a exponenciação 2^3(=8), então são
calculadas as multiplicações e divisões 10/2(=5) e 5*3(=15), e finalmente as adições resultando em
2+5+15+8(=30).
Al teração da Precedência
A utilização de parênteses dentro de uma expressão altera a ordem de precedência dos operadores.
Operandos entre parênteses são analisados antes dos que se encontram fora dos parênteses. Se existirem
mais de um conjunto de parênteses não-aninhados, o grupo mais a esquerda será avaliado primeiro e
assim sucessivamente.
58
No exemplo acima primeiro será calculada a exponenciação 2^3(=8). Em seguida 2+10(=12) será
calculado, 2+5(=7) calculado, e finalmente a divisão e a multiplicação serão efetuadas, o que resulta em
12/7*3+8(=13.14).
Se existirem vários parênteses aninhados, ou seja, colocados um dentro do outro, a avaliação ocorrerá do
parênteses mais intero em direção ao mais externo.
01 X := 10
02 Y := "X + 1"
A variável X é atribuída com o valor 10, enquanto a variável Y é atribuída com a string de caracteres
contendo "X + 1".
A terceira linha utiliza o operador de macro. Esta linha faz com que o número 11 seja atribuído à variável
B. Pode-se perceber que esse é o valor resultante da expressão em formato de caractere contida na
variável Y.
Utilizando-se uma técnica matemática elementar, a substituição, temos que na segunda linha, Y é definido
como "X + 1", então pode-se substituir Y na terceira linha:
03 B := &"X + 1"
03 B := X + 1
Pode-se perceber que o operador de macro remove as aspas, o que deixa um pedaço de código para ser
executado. Deve-se ter em mente que tudo isso acontece em tempo de eecução, o que torna tudo muito
dinâmico. Uma utilização interessante é criar um tipo de calculadora, ou avaliador de fórmulas, que
determina o resultado de algo que o usuário digita.
O operador de macro tem uma limitação: variáveis referenciadas dentro da string de caracteres (X
nos exemplos anteriores) não podem ser locais.
59
Em AdvPl, todas as estruturas de controle podem ser "aninhadas" dentro de todas as demais estruturas
contanto que estejam aninhadas propriamente. Estruturas de controle têm um identificador de início e um
de fim, e qualquer estrutura aninhada deve se encontrar entre estes identificadores.
Também existem estruturas de controle para determinar que elementos, comandos, etc em um programa
serão compilados. Estas são as diretivas do pré-processador #ifdef...#endif e #ifndef...#endif. Consulte a
documentação sobre o pré-processador para maiores detalhes.
Em AdvPl existem dois comandos para a repetição de seções de código. O comando FOR...NEXT e o
comando WHILE...ENDDO.
O Comando FOR...NEXT
A estrutura de controle FOR...NEXT, ou simplesmente o loop FOR, repete uma seção de código em um
número determinado de vezes.
Si n t a x e
Comandos...
60
[EXIT]
[LOOP]
NEXT
Pa r â m e t r o s
Variavel Especifica uma variável ou um elemento de uma matriz para atuar como um
contador. A variável ou o elemento da matriz não precisa ter sido declarado antes
da execução do comando FOR...NEXT. Se a variável não existir, será criada como
uma variável privada .
nValor Inicial nValorInicial é o valor inicial para o contador; nValorFinal é o valor final para o
TO nValorFinal contador. Pode-se utilizar valores numéricos literais, variáveis ou expressões,
contanto que o resultado seja do tipo de dado numérico.
LOOP Retorna o controle diretamente para a cláusula FOR sem executar o restante dos
comandos entre o LOOP e o NEXT. O contador é incrementadou ou decrementado
normalmente, como se o NEXT tivesse sido alcançado. Pode-se colocar o comando
LOOP em qualquer lugar entre o FOR e o NEXT.
Co m e n t á r i o s
Uma variável ou um elemento de uma matriz é utilizado como um contador para especificar quantas vezes
os comandos AdvPl dentro da estrutura FOR...NEXT são executados. Os comandos AdvPl depois do FOR
são executados até que o NEXT seja alcançado. O contador (Variavel) é então incrementado ou
decremantado com o valor em nIncremento (se a cláusula STEP for omitida, o contador é incrementado
em 1). Então, o contador é comparado com o valor em nValorFinal. Se for menor ou igual ao valor em
nValorFinal, os comandos seguintes ao FOR são executados novamente. Se o valor for maior que o
contido em nValorFinal, a estrutura FOR...NEXT é terminada e o programa continua a execução no
primeiro comando após o NEXT.
Ex e m p l o
Local nCnt
Local nSomaPar := 0
61
nSomaPar += nCnt
Next
cValToChar(nSomaPar) )
Return
Este exemplo imprime a soma dos 100 primerios números pares. A soma é obitida através da repetição do
cálculo utilizando a própria variável de contador. Como a cláusula STEP está sendo utilizada, a variável
nCnt será sempre incrementada em 2. E como o contador começa com 0, seu valor sempre será um
número par.
O Comando WH I LE...ENDDO
A estrutura de controle WHILE...ENDDO, ou simplesmente o loop WHILE, repete uma seção de código
enquanto uma determinada expressão resultar em verdadeiro (.T.).
Si n t a x e
Comandos...
[EXIT]
[LOOP]
ENDDO
Pa r â m e t r o s
lExpressao Especifica uma expressão lógica cujo valor determina quando os comandos entre o WHILE
e o ENDDO são executados. Enquanto o resultado de lExpressao for avaliado como
verdadeiro (.T.), o conjunto de comandos são executados.
Comandos Especifica um ou mais instruções de comando AdvPl que serão executadas enquanto
lExpressao for avaliado como verdadeiro (.T.).
62
LOOP Retorna o controle diretamente para a cláusula WHILE sem executar o restante dos
comandos entre o LOOP e o ENDDO. A expressão em lExpressao é reavaliada para a
decisão se os comandos continuarão sendo executados.
Co m e n t á r i o s
Os comandos entre o WHILE e o ENDDO são executados enquanto o resultado da avaliação da expressão
em lExpressao permanecer verdadeiro (.T.). Cada palavra chave WHILE deve ter uma palavra chave
ENDDO correspondente.
Ex e m p l o
nAux := Int(nAux / 2)
nSomaPar += nCnt
Next
cValToChar(nSomaPar) )
Return
Desviando a Execução
Estruturas de desvio são deseginadas para executar uma seção de código se determinada condição lógica
resultar em verdadeiro (.T.). Em AdvPl existem dois comandos para execução de seções de código de
acordo com avaliações lógicas. O comando IF...ENDIF e o comando DO CASE...ENDCASE.
O Co mando IF...ENDI F
Executa um conjunto de comandos baseado no valor de uma expressão lógica.
63
Si n t a x e
IF lExpressao
Comandos
[ELSE
Comandos...]
ENDIF
Pa r â m e t r o s
lExpressao Especifica uma expressão lógica que é avaliada. Se lExpressao resultar em verdadeiro
(.T.), qualquer comando seguinte ao IF e antecedente ao ELSE ou ENDIF (o que ocorrer
primeiro) será executado.
Se lExpressao resultar em falso (.F.) e a cláusula ELSE for definida, qualquer comando
após essa cláusula e anterior ao ENDIF será executada. Se a cláusula ELSE não for
definida, todos os comandos entre o IF e o ENDIF são ignorados. Neste caso, a execução
do programa continua com o primeiro comando seguinte ao ENDIF.
Co m e n t á r i o s
Pode-se aninhar um bloco de comando IF...ENDIF dentro de outro bloco de comando IF...ENDIF. Porém,
para a avaliação de mais de uma expressão lógica, deve-se utilizar o comando DO CASE...ENDCASE.
Ex e m p l o
O Comando DO CASE...ENDCASE
Executa o primeiro conjunto de comandos cuja expressão condicional resulta em verdadeiro (.T.).
Si n t a x e
DO CASE
CASE lExpressao1
Commandos
[CASE lExpressao2
Commandos
...
CASE lExpressaoN
Commandos]
[OTHERWISE
Commandos]
ENDCASE
Pa r â m e t r o s
64
CASE Quando a primeira expressão CASE resultante em verdadeiro (.T.) for encontrada, o
lExpressao1 conjunto de comandos seguinte é executado. A execução do conjunto de comandos
Comandos... continua até que a próxima cláusula CASE, OTHERWISE ou ENDCASE seja
encontrada. Ao terminar de executar esse conjunto de comandos, a execução
continua com o primeiro comando seguinte ao ENDCASE.
OTHERW ISE Se todas as expressões CASE forem avaliadas como falso (.F.), a cláusula
Commandos OTHERWISE determina se um conjunto adicional de comandos deve ser executado.
Se essa cláusula for incluida, os comandos seguintes serão executados e então o
programa continuará com o primeiro comando seguinte ao ENDCASE. Se a cláusula
OTHERWISE for omitida, a execução continuará normalmente após a cláusula
ENDCASE.
Co m e n t á r i o s
Ex e m p l o
DO CASE
CASE nMes <= 3
cPeriodo := "Primeiro Trimestre"
CASE nMes >= 4 .And. nMes <= 6
cPeriodo := "Segundo Trimestre"
CASE nMes >= 7 .And. nMes <= 9
cPeriodo := "Terceiro Trimestre"
OTHERWISE
cPeriodo := "Quarto Trimestre"
ENDCASE
Return
65
Notas:
• Palavras reservadas não podem ser utilizadas para variáveis, procedimentos, ou funções.
• Funções reservadas são pertencentes ao compilador e portanto não podem ser redefinidas por uma
aplicação.
• Todosos identifadores que começarem com um ou mais caracters de sublinhado (_) são utilizados
como identificadores internos e portanto são também reservados.
• de correto funcionamento
66
• eficiente
• legível
• reutilizável
• extensível
• portável
Após anos de experiência na utilização de linguagens padrão xBase e do desenvolvimento da linguagem
AdvPl, algumas técnicas para uma programação otimizada e eficiente foram reconhecidas. A utilização das
técnicas a seguir, visa buscar o máximo aproveitamento dos recursos da linguagem com o objetivo de
criar programas com estas características.
Local lOk
lOk := GetOk(lDefault)
If lOk
Return .T.
Else
Return .F.
Endif
Return nil
Utilizando-se apenas o critério "a função funciona corretamente?", a função GetAnswer é perfeita. Recebe
um parâmetro lógico com a resposta padrão e retorna um valor lógico dependente da opção escolhida
pelo usuário em uma função de diálogo "sim/não" designada para isso. Pode entretanto ser melhorada,
particularmente se eficiência for considerada como um critério para um código melhor. Eficiência
tipicamente involve a utilização de poucos recursos de máquina, poucos chamadas de funções ou tornar
mais rápido um processo.
Ou melhor:
67
Return GetOk(lDefault)
Com a otimização do código da função GetAnswer, pode facilmente verificar que a mesma não realiza
nada adicional à chamada de GetOk, podendo ser substituída por uma chamada direta desta, continuando
a funcionar corretamente.
Nenhum comentário substitui um código claramente escrito, e este não é um um acidente. Considere o
exemplo:
O tamanho da variável cVar não é evidente por si só e não é facilmente verificado. Estes mesmos 10
espaços estariam mais óbvios e ainda assim garantidos se a instrução fosse escrita como:
cVar := Space(10)
O mesmo princípio pode ser aplicado para qualquer string longa de caracteres repetidos. A função
Replicate pode ser utilizada como a seguir:
Este tipo de programação deixa o código fácil de digitar, fácil de ler e mais flexível.
Simplicidade na criação de instruções torna a programação e até mesmo a execução mais rápida.
Considere a linha de código:
Se o valor da variável nVar for igual a zero (0) no momento da execução desta linha de código, ambas as
comparações separadas pelo operador lógico .Or. serão efetuadas: Após ser avaliada, a primeria
comparação irá falhar. A segunda comparação será então avaliada e falhará também. Como resultado, o
código existente dentro da estrutura de fluxo If não será executado. Tal código somente será executado
quando o valor desta variável for maior OU menor do que zero. Ou seja, sempre que for DIFERENTE de
zero, o que torna a linha a seguir mais eficiente:
If nVar != 0
68
Este tipo de alteração torna o código mais legível e o processamento mais rápido, evitando a avaliação de
instruções desnecessariamente.
Existem outras situações onde a simplificação pode ser utilizada. A expressão de avaliação a seguir:
If cVar $ "ABCD"
A melhor solução é aquela que envolve o problema imediato e previne problemas no futuro. Considere o
exemplo:
Exceto contando-se os caracteres, não existe maneira de saber se o número de caracteres de exclamação
é o esperado. Enquanto isto é um problema, existem algo mais grave. A expressão de pictu re é estática.
Se no futuro for necessário ajustar o tamanho da variável cVar, será necessário localizar todos os lugares
no código onde esta máscara de picture está sendo utilizada para ajuste manual. Existe uma opção
dsolução de de auto-ajuste disponível que é fácil de digitar e tem a garantia de executar a tarefa
igualmente (tornar todos os caracteres maiúsculos):
Se a solução parece complexa, provavelmente é porque o caminho escolhido está levando a isso. Deve-se
sempre se perguntar porque alguém desenvolveria uma linguagem que requisite tantos comandos
complicados para fazer algo simples. Na grande maioria dos casos, existe uma solução mais simples. O
exemplo abaixo deixa isso bem claro:
69
Utilizados devidamente, os operadores de incremento e decremento tornam o código mais fácil de ler e
possivelmente um pouco mais rápidos. Ao contrário de escrever adições simples como:
nVar := nVar + 1
nVar := nVar -1
++nVar
--nVar
Deve-se apenas tomar cuidado com a precedência destes operadores, pois o "++" ou o "--" podem
aparecer antes ou depois de uma variável, e em alguns casos quando a variável for utilizada dentro de
uma expressão, a prefixação ou sufixação destes operadores afetará o resultado. Para maiores detalhes,
consulte a documentação de operadores da linguagem AdvPl.
Existe uma diferença entre um bom hábito e perda de tempo. Algumas vezes estes conceitos podem estar
muito próximos, mas um modo de diferenciá-los é balancear os benefícios de realizar alguma ação contra
o problema que resultaria se não fosse executada. Observe o exemplo:
Local nCnt := 0
For nCnt := 1 To 10
<código>
Next nCnt
Neste exemplo não há nenhum ponto negativo e nada errado ocorrerá se a variável não for inicializada,
portanto é aconselhável evitar este tipo de inicialização, pois não torna o código mais seguro e também
não expressa a intenção do código mais claramente.
Local nCnt
<código>
EndDo
70
Em AdvPl, variáveis não inicializadas sempre tem seu valor contendo nulo (nil) a princípio, o que fará com
que uma exceção em tempo de execução aconteça quando a instrução de repetição while for executada.
Diferentemente do primeiro exemplo, onde a inicialização da variável não fazia diferença alguma, neste
segundo exemplo a inicialização é absolutamente necessária. Deve-se procurar inicializar variáveis
numéricas com zero (0) e variáveis caracter com string nula ("") apenas quando realmente necessário.
Quando se está trabalhando em uma simples rotina, deve-se tomar algum tempo para explorar duas ou
três diferentes abordagens. Quando se está trabalhando em algo mais complexo, deve-se planejar
prototipar algumas a mais. Considere o seguinte código:
If cHair = "A"
Else
If cHair = "B"
Else
If cHair = "C"
Else
If cHair = "D"
Else
Endif
Endif
Endif
Endif
Um código de uma única letra, (A até E), foi informado para indicar a cor de cabelo. Este código foi então
convertido e armazenado como uma string. Pode-se notar que a cor "Preto" será atribuída se nenhuma
outra opção for verdadeira.
Uma alternativa que reduz o nível de identação torna o código mais fácil de ler enquanto reduz o número
de comandos replace:
Do Case
71
cColor := "Loira"
cColor := "Morena"
cColor := "Ruiva"
cColor := "Grisalho"
OtherWise
cColor := "Preto"
EndCase
Constan t es em Maiúsculo
Isto é uma convenção que faz sentido. Em AdvPl, como em C por exemplo, a regra é utilizar todos os
caracteres de uma constante em maiúsculo, a fim de que possam ser claramente reconhecidos como
constantes no código, e que não seja necessários lembrar onde foram declarados.
Este é um hábito que todo programador deve desenvolver. Não consome muito esforço para manter o
código alinhado durante o trabalho, porém quando necessário pode-se utilizar AP6 IDE para a reidentação
de código.
Considere o exemplo:
While !SB1->(Eof())
If mv_par01 = SB1->B1_COD
dbSkip()
Loop
Endif
Do Case
72
TrataLocal(SB1->B1_COD,SB1->B1_LOCAL)
TrataDefeito(SB1->B1_COD)
OtherWise
TrataCompra(SB1->B1_COD,SB1->B1_LOCAL)
EndCase
dbSkip()
EndDo
A utilização da identação seguindo as estruturas de controle de fluxo (while, if, case, etc) torna a
compreensão do código muito mais fácil:
While !SB1->(Eof())
If mv_par01 = SB1->B1_COD
dbSkip()
Loop
Endif
Do Case
TrataLocal(SB1->B1_COD,SB1->B1_LOCAL)
TrataDefeito(SB1->B1_COD)
OtherWise
TrataCompra(SB1->B1_COD,SB1->B1_LOCAL)
EndCase
dbSkip()
EndDo
Espaços em branco extras tornam o código mais fácil para a leitura. Não é necessário imensas áreas em
branco, mas agrupar pedaços de código através da utilização de espaços em branco funciona muito bem.
Costuma-se separar parâmetros com espaços em branco.
73
Com o objetivo de tornar o código mais fácil de ler e imprimir, as linhas do código não devem estender o
limite da tela ou do papel. Podem ser "quebradas" em mais de uma linha de texto utilizando o ponto-e-
vírgula (;).
Uma convenção amplamente utilizada é a de capitular as palavras chaves, funções, variáveis e campos
utilizando uma combinação de caracteres em maiúsculo e minúsculo, visando facilitar a leitura do código
fonte. O código a seguir:
local ncnt
ntotal += ncnt * 2
enddo
Local nCnt
nTotal += nCnt * 2
EndDo
A Notação Húngara é muito comum entre programadores xBase e de outras linguagens. A documentação
do AdvPl utiliza esta notação para a descrição das funções e comandos e é aconselhável sua utilização na
criação de rotinas, pois ajuda a evitar pequenos erros e facilita a leitura do código. Para maiores detalhes,
consulte a documentação sobre a Notação Húngara disponível na documentação da linguagem AdvPl.
A principal vantagem da liberdade na criação dos nomes de variáveis é a facilidade de identificação da sua
utilidade. Portanto deve-se utilizar essa facilidade o máximo possível. Nomes sem sentido apenas tornarão
difícil a identificação da utilidade de uma determinada variável, assim como nomes extremamente curtos.
Nem sempre a utilização de uma variável chamada i é a melhor saída. Claro, não convêm criar uma
variável com um nome muito longo que será utilizada como um contador, e referenciada muitas vezes no
código. O bom senso deve ser utilizado.
Criar variáveis como nNumero ou dData também não ajudam na identificação. A Notação Húngara já está
sendo utilizada para isso e o objetivo do nome da variável deveria ser identificar sua utilização, não o tipo
de dado utilizado. Deve-se procurar substituir tais variáveis por algo como nTotal ou dCompra.
O mesmo é válido para nomes de funções, que devem descrever um pouco sobre o que a função faz.
Novamente nomes extremamente curtos não são aconselháveis.
74
Comentários são muito úteis na documentação de programas criados e para facilitar a identificação de
processos importantes no futuro. Devem sempre ser utilizados.
Sempre que possível, funções criadas devem ter uma breve descrição do seu objetivo, parâmetros e
retorno. Além de servir como documentação, os comentários embelezam o código ao separar as funções
umas das outras.
Os comentários devem ser utilizados com bom senso, pois reescrever a sintaxe AdvPl em português torna-
se apenas perda de tempo:
Seja oferecendo assistência, exibindo mensagens de aviso ou mantendo o usuário informado do estado de
algum processo, as mensagens devem refletir o tom geral e a importância da aplicação. Em termos
gerais, deve-se evitar ser muito informal e ao mesmo tempo muito técnico.
Esse tipo de mensagem pode dar informações demais para o usuário e deixá-lo sentindo-se desconfortável
se não souber o que significa "reindexando", etc. E de fato, o usuário não devia ser incomodado com tais
detalhes. Apenas a frase "Aguarde, indexando." funcionaria corretamente, assim como palavras
"processando" ou "reorganizando".
Outra boa idéia é evitar a referencia a um item corrente de uma tabela como um "registro":
Se a operação estiver sendo efetuada em um arquivo de clientes, o usuário deve ser questionado sobre a
remoção do cliente corrente, se possível informando valores de identificação como o código ou o nome.
Apesar do AdvPl suportar a abreviação de comandos em quatro letras (por exemplo, repl no lugar de
replace) não há necessidade de utilizar tal funcionalidade. Isto apenas torna o código mais difícil de ler e
não torna a compilação mais rápida ou simples.
Não deve-se criar constantes para expressões complexas. Isto tornará o código muito difícil de
compreender e poderá causar erros primários, pois pode-se imaginar que uma atribuição é efetuada a
uma variável quando na verdade há toda uma expressão disfarçada:
75
If ISDISK == 1
NUMLINES := 55
Endif
NUMPAGES += 1
A impressão que se tem após uma leitura deste código é de que valores estão sendo atribuidos às
variáveis ou que constantes estão sendo utilizadas. Se o objetivo é flexibilidade, o código anterior deve
ser substituído por:
#define NUMLINES 1
#define NUMPAGES 2
#define ISDISK 5
If aReturn[ISDISK] == 1
aPrintDefs[ NUMLINES ] := 55
Endif
aPrintDefs[ NUMPAGES ] += 1
Dada sua natureza binária, tudo pode ou não acontecer dentro de um computador. Adicionar pedaços de
código apenas para "garantir a segurança" é freqüentemente utilizado como uma desculpa para evitar
corrigir o problema real. Isto pode incluir a checagem para validar intervalos de datas ou para tipos de
dados corretos, o que é comumente utilizando em funções:
nVal := 0
Endif
O ganho é irrisório na checagem do tipo de dado do parâmetro já que nenhum programa corretamente
escrito em execução poderia enviar uma string ou uma data para a função. De fato, este tipo de "captura"
é o que torna a depuração difícil, já que o retorno será sempre um valor válido (mesmo que o parâmetro
recebido seja de tipo de dado incorreto). Se esta captura não tiver sido efetuada quando um possível erro
de tipo de dado inválido ocorrer, o código pode ser corrigido para que este erro não mais aconteça.
76
No caso de mensagens e strings de texto, a centralização é um bom negócio. Pode-se colocar mensagens,
caminhos para arquivos, e mesmo outros valores em um local específico. Isto os torna acessíveis de
qualquer lugar no programa e fáceis de gerenciar.
Por exemplo, se existe uma mensagem comum como "Imprimindo, por favor aguarde..." em muitas
partes do código, corre-se o risco de não seguir um padrão para uma das mensagens em algum lugar do
código. E mantê-las em um único lugar, como um arquivo de cabeçalho, torna fácil a produção de
documentação e a internacionalização em outros idiomas.
Funções
Templates
Comando GET
77
Funções
R Insere caracteres diferentes dos caracteres de template na exibição mas não insere-os na
variável do GET
S<n> Permite rolamento horizontal do texto dentro do GET, <n> é um número inteiro que identifica
o tamanho da região
Templates
9 Permite apenas dígitos para qualquer tipo de dado, incluindo o sinal para numéricos
Prefácio
78
Existe um ditado chinês que diz: “O Homem não tropeça em montanhas, tropeça em pedregulhos, areia,
pequenos buracos, mas nunca em uma montanha”.
Isso nos remete a pensar que onde erramos é exatamente no simples, naquele detalhe quase
imperceptível e que tem um valor muito grande para o todo. Avaliemos do ponto de vista humano; será
tão difícil cumprimentar a todos, sermos mais amigos, mais serenos nas decisões e companheiros uns dos
outros e trabalharmos em equipe? Por que muitas vezes não o fazemos? Por que insistimos no
individualismo e no mal-humor? Não seria mais fácil, até mesmo óbvio, estarmos mais bem-humorados e
dispostos a trabalhar em equipe, trocarmos conhecimento e discernimento nas decisões, pensarmos mais
no todo porém se importando com as partes que o compõe?
Seria mais interessante se ao caminharmos por um parque, prestássemos mais atenção nas árvores, no
caminho, nas flores, no canto dos passarinhos sem se esquecer do objetivo do passeio, sem perder a
noção de tempo e distância, mas curtindo muito a paisagem, o detalhe.
Agora vamos traçar um paralelo com o nosso dia a dia. Não seria melhor ao reservarmos um fonte,
verificarmos com mais atenção:
As mensagens? Afinal é tão comum nos depararmos com textos completamente sem sentido.
Os helps? Damos pouca atenção a eles e nos esquecemos que é a primeira coisa que o usuário tenta.
Imaginem algumas ligações menos por causa de uma simples documentação a mais! Aquele ponto de
entrada que criamos e não pensamos nos supostos parâmetros que nosso pessoal em campo pode querer,
ou mesmo no retorno mais adequado para aquela função.
Por que ao invés de focarmos nossos esforços para “matarmos” o BOPS, não avaliamos o fonte para
evitarmos NOVOS BOPS? Ao resolver uma ocorrência lembre-se de todos os pontos de implicação da sua
atividade. O que isso irá impactar no serviço do outro? Sem falar em documentar no Quark!
Vamos trazer o comportamento do parque para o nosso trabalho também. Ao programar vamos nos ater
aos detalhes, sermos mais críticos, pensarmos que aquela instrução a mais, significa muito para o sistema
e que lá na frente, se tratado com descuido, pode causar problemas.
Tenha convicção que, se agirmos de maneira mais focada aos nossos propósitos, o passeio ou melhor a
programação, será muito mais entusiasmada, produtiva e com uma margem de erro bem menor. Com
esse comportamento quem ganha somos nós; Microsiga!. Só assim teremos mais tempo de irmos ao
parque no final de semana.
Lembre-se que não adianta decidirmos passear no parque do Ibirapuera no domingo, e não estarmos com
a cabeça voltada para o passeio, ao invés disso pensarmos no trabalho, na DLLl que não comunica, no
BOPS que não foi baixado, pois se assim for, estaremos tão voltados para outros fins que não curtiremos
o passeio. Pense que para passear, ou melhor, programar, a regra também é valida, não adianta nem ao
menos tentarmos se não estivermos concentrados para isso.
Enfim, quer uma prova de trabalho em equipe com um alto nível de qualidade e detalhes; este manual,
que foi constituído em apenas 2 dias, com a colaboração de mais de 20 pessoas, focadas em seus
objetivos, se atentando cada um com o seu tema. O resultado? Um trabalho excelente, um documento
para nos ajudar a sermos melhores e não errarmos no fácil!
79
De acordo com essa definição, se pretendemos utilizar nosso bem mais precioso em nosso trabalho,
vamos precisar desenvolver alguns hábitos:
Devemos estudar o programa antes de começar a desenvolver. Imagine prestar um concurso ou fazer
uma prova sem estudar. Vai ganhar um zero na certa! No programa não será diferente!
Fazer um levantamento dos programas que sofrerão as conseqüências das alterações realizadas. Todos
esses programas deverão ser testados juntamente com o programa alterado.
Antes de criar uma função, consulte o Help Microsiga ou os colegas de trabalho, pois esta função já pode
ter sido criada.
Ao criar uma função, certifique-se de que no cabeçalho conste algumas informações básicas como:
descrição da função, sintaxe, definição dos parâmetros e autor. É comum ao desenvolver uma função,
utilizarmos outra já pronta como exemplo, e neste momento o “copiar/colar” nos faz esquecer de alterar
estas informações.
Imagine se alguém desenvolver uma função inconsistente e esquecer de trocar o seu nome no cabeçalho.
Devemos assumir a responsabilidade de nossos atos.
Ao fazer a documentação das alterações realizadas, certifique-se de que as informações estão claras, não
só para o seu entendimento mas para que os colegas não percam tempo tentando entender-las.
Ao realizar os testes, defina critérios. Antes de começar defina onde quer chegar. Não basta consistir suas
alterações. O fato de suas alterações estarem funcionando como previstas não garante a não existência
de erros.
Não limite-se a testar sua alteração na base que você utilizou durante o desenvolvimento, pois você criou
o ambiente perfeito para que o programa funcione.
Pode parecer um pouco trabalhoso passar por estes processos no decorrer do desenvolvimento do
sistema, mas se medidas como estas não forem tomadas, o que era extremamente simples se tornará
extremamente trabalhoso.
Qual profissional da área de informática ainda não se deparou com um código fonte que parecia estar
escrito em outro dialeto mesmo com todo conhecimento adquirido naquela linguagem, este fato
geralmente ocorre pela má utilização de sintaxes complexas que nem sempre significam um bom
funcionamento do sistema.
Um profissional da área de informática não possui nenhum modelo padrão para desenvolver os seus
algoritmos, porém é necessária a aplicação da ética profissional para que se possa desenvolver algoritmos
de maneira simples e correta, este conceito se baseia nos seguintes aspectos :
Existem alguns erros que com um pouco de atenção, podem ser evitados, tais como:
Ao declarar uma variável, verifique qual a necessidade de ter essa variável e qual o tipo e a sua classe;
80
Salve a ordem e a área e o registro do arquivo que será utilizadopara que no final do processo se recupere
estes valores;
Evite retornar da função antes do seu final, ou seja, crie preferencialmente um único retorno;
Quando for gravar um arquivo que utiliza campos de outros arquivos, posicione todos os arquivos e
registros antes de iniciar a gravação, e descreva o alias do campo;
Quando possível utilize a linguagem SQL, pois minimiza o tempo de execução em muitos processos.
Todos sabemos o quanto é difícil elaborar e manter uma documentação técnica atualizada, ainda mais
aqui na Microsiga, cuja dinâmica dos acontecimentos muitas vezes impede que isso seja viabilizado.
Diante desse cenário, o que nos resta? Obviamente que pelo menos os programas sejam documentados,
bem documentados.
Documentar bem, não significa que tenhamos que escrever dezenas de linhas de comentários a cada linha
de código. Significa que os comentários têm passar alguma informação relevante. Vemos comentários
assim: “compara A com B” e só. Isso é óbvio, a leitura do código já nos diz isso. A documentação deve se
ater a conceitos, por exemplo: “Se A for maior que B, o arquivo de saldos será atualizado, caso contrário
o registro será rejeitado para que o saldo não fique negativo.”. Isto sim transmite alguma informação.
Também se pode utilizar desse recurso para fazer lembretes a fatos importantes que, se forem deixados
de lado, podem comprometer o funcionamento das rotinas.
Por exemplo: “Ao acionar esta função, o arquivo XXX DEVE estar posicionado no índice 1”.
E os cabeçalhos? Quantos programas são “aproveitados” e nem sequer o nome do autor é trocado? Se o
analista X tivesse escrito todos programas que aparece como autor ele deveria ter começado na época do
Charles Babage. O cabeçalho das funções de conter o nome na dita cuja, autor, data de criação, uma
descrição sumária de sua funcionalidade, a sintaxe e por último, mas não menos importante, a descrição
dos argumentos de entrada e saída. A respeito desse último item deve-se ter especial atenção nas
manutenções, pois novos argumentos são criados e nem sempre são declarados nessa seção da
documentação do cabeçalho, isso é muito grave.
No IDE do PROTHEUS existem opções bastante interessantes para nos auxiliar nessa tarefa. Experimente
as opções Inserir, Documentação de cabeçalho e Inserir, Documentação de Explicação.
Existe ainda um tipo de documentação que nem sempre é observada, é aquela inerente ao próprio código.
Programas cujas variáveis são declaradas como nX, cVAR1, dAUX, nNUM, etc., são extremamente difíceis
de entender e pior, manter. É conveniente que os nomes das variáveis retratem seu uso ou destino. Por
exemplo: dDataDeS ou dDataDeE. Segundo as convenções da Microsiga, variáveis do tipo DATA devem
ser iniciadas pela letra “d”. Assim “Data”, não acrescenta nada ao entendimento do que a variável
representa. Nos sobrou o “dES” e o “dEE” para informar para que diados serve a bendita variável. Será
saída, solução, saldo? Entrada, Estorno, Estoque? Que tal isso: dSeguro e dEntrega?
Enfim, como foi dito, não é preciso escrever um livro a cada programa, basta ser objetivo e se colocar na
posição de quem não conhece o programa tão pouco o assunto. Algum dia você mesmo poderá estar
nessa posição.
O cabeçalho do programa é utilizado para identificar informações gerais sobre a rotina, seu autor, data,
entre outras informações. É importante que esteja preenchida de forma correta e atualizada. Lembre-se
de que nada adianta um cabeçalho que não informe nada ou pior ainda, com informações errôneas.
81
Lembre-se que um bom livro começa com um bom prefácio, e um bom programa começa com um
cabeçalho útil e legível.
Criação de Variáveis
Na criação de uma variável deve-se ter em mente alguns pontos fundamentais:
• A declaração
• O tipo de variável
• A função CRIAVAR()
• A inicialização
• Padronização de variáveis
A Declaração
Deve ser feita sempre no início da rotina que for utilizá-la, como no exemplo:
Function a910VerCod()
Return
O tipo de variável serve para identificar a utilização que a mesma terá no decorrer da rotina. Toda variável
deve estar tipada durante sua criação. Quando programamos nativamente em “C”, isto se torna
obrigatório. Devemos fazer o mesmo no AP5, pois isto demonstra que a variável foi conscientemente
declarada.
PUBLIC: Esta variável será inicializada em um valor lógico falso (.F.) até que seja atribuído um valor
específico a ela. Esta variável permanece definida por toda a duração da aplicação e pode ser vista (assim
como usada, alterada e avaliada) por qualquer função. Esta variável gera um token (indicação) na tabela
de símbolos, isto significa que o módulo principal conterá símbolos para esta classe de variável, o que, por
sua vez, ocupa mais espaço de memória. Deve-se evitar a utilização deste tipo, a não ser em casos
extremos.
PRIVATE: Esta variável será inicializada em valor nulo (NIL) e uma vez declarada, permanecerá assim
durante toda a duração do fluxo da função, até que este volte ao procedimento inicial que a chamou. Em
essência, uma variável de memória PRIVATE inicializada logo no início do Protheus, agirá como um
variável PUBLIC. Esta variável pode ser vista por uma sub-rotina da função e modificada de maneira
correspondente. Esta variável também gera um token na tabela de símbolos comentada acima.
LOCAL: Esta variável de memória será inicializada com valor nulo (NIL) e só é visível dentro da função que
a inicializa, mesmo que esta última, contenha funções incorporadas a seu conteúdo. Este tipo de variável
é o mais adequado a ser utilizado em funções, pois não gera símbolos na tabela de símbolos, por
conseqüência ocupa pouco espaço de memória e, o compilador avalia as variáveis LOCAL e STATIC mais
82
rapidamente que os outros tipos (PUBLIC e PRIVATE). Cuidado para não sucumbir à teoria de que se pode
obter economia de memória, mudando qualquer referência PRIVATE para uma referência LOCAL. Se você
fizer isso, as funções podem não funcionar corretamente, embora funcionassem na versão anterior às
alterações.
STATIC: A variável STATIC é idêntica à classe de armazenamento LOCAL, com uma exceção. Uma variável
STATIC é retida dentro de sua sub-rotina, mesmo depois que o fluxo da função a tenha deixado. Isto é
particularmente útil para funções independentes tipo “caixa-preta”, que contém seu próprio conjunto de
variáveis exclusivas e devem manter esses valores de interação em interação.
I nicialização
Quando não atribuímos nenhum valor a uma variável no momento de sua declaração, corremos o risco de
utilizá-la com valor “NIL” e causar erros fatais. Por isso, a inicialização de uma variável é de extrema
importância.
Padronização de Variáveis
É importante que ao lermos o nome de uma variável, possamos saber se o seu tipo é numérico, caracter,
data ou lógico. O nome da variável de get não deve coincidir com uma variável de outro programa, pois
toda variável de get possui um help específico.
Exemplo:
a variável DBaixa (get da baixa no programa de Títulos a Receber), já possui um texto help que indica seu
conteudo e não deverá ser criada outra variável para outra finalidade com este mesmo nome.
N -> Numéricas
L -> Lógicas
D -> Data
C -> Caracter
O -> Objeto
Esta função cria uma variável, retornando o valor do campo, de acordo com o dicionário de dados. Avalia
o inicializador padrão e retorna o conteúdo de acordo com o tipo de dado definido no dicionário.
Sintaxe
uRet := CriaVar(cCampo,lIniPad,cLado)
Onde :
Uret -> tipo de retorno de acordo com o dicionário de dados, considerando inicializador padrão.
LiniPad -> Indica se considera (.T.) ou não (.F.) o inicializador padrao (X3_RELACAO)
83
Na criação de um relatório algumas variáveis e seus tipos são convencionados para a utilização da
biblioteca de funções de relatório.
Matriz contendo as ordens de layout para a impressão. Caso não existam várias
ordens esta matriz deve estar vazia. Ex.: aOrd := {"Código", "Descrição",
aOrd Private
"Telefone"} -> O layout do relatório vai depender da ordem selecionada na tela
de configuração de impressão
aLinha Private Matriz que contem informações para impressão de relatórios cadastrais
84
Como no mesmo arquivo de dados, poderemos ter registros de várias filiais, desta forma ficará garantido
o posicionamento no primeiro registro da filial corrente.
If ! SB1->(dbSeek(xFilial("SB1")))
Endif
Mesmo que seja óbvio a existência do registro, faça o teste pois o programa deve prever que a base de
dados não é tão confiável como deveria, e um alerta ajuda a identificar estes casos. Em casos de
relatórios, atentar-se para imprimir a mensagem de forma consciente.
Se for executada a função RECLOCK(cAlias, .F.), para alteração do registro atual, em um arquivo no
estado de EOF() (caso falhe um DBSEEK() ) será abortado o programa e gravado um arquivo texto de
nome MSRLOCK.EOF que poderá ser usado para averiguações.
O comando SOFTSEEK determina se será usada uma busca relativa durante um procura em um banco de
dados. Se este comando estiver em ON, e for utilizada uma função DBSEEK(), e nenhuma
correspondência for encontrada, o ponteiro de registro ficará no próximo registro do índice que possua um
valor mais alto que a expressão utilizada nesta função. Este comando deverá ser utilizado com a máxima
atenção, pois caso esteja ligado, poderá localizar um registro errado.
Quanto ao comando DO WHILE não esquecer de incluir a condição referente à filial, quando esta leitura for
de registros de uma filial). Exemplo :
dbSelectArea("SB1")
dbSeek(xFilial("SB1"))
// Processamento
dbSkip()
Enddo
Ao criar uma função que irá desposicionar registros, use a função GETAREA() e RESTAREA(), para voltar
tudo à posição original. Exemplo:
Dbselectarea("SD1")
SD1->(dbsetorder(3))
85
// Processamento
Dbskip()
Enddo
Função Posicione
Podemos também buscar uma informação em determinado campo usando apenas uma função.
Sintaxe:
Exemplo:
Desta forma, será efetuada uma busca no SB1, na ordem 1, chave da busca xFilial("SB1") + cCodigo e
será retornado o conteúdo do campo "B1_DESC". Note que esta função, não restaura a posição original do
arquivo alvo (no caso SB1).
É necessário colocar a FILIAL do arquivo na chave passada como parâmetro, caso ela exista na chave do
indice.
Função Ex istcpo
Sintaxe :
ExistCpo(cAlias,cChave,nOrdem)
Exemplo :
Desta forma, será efetuada uma busca no SB1, na ordem 1, chave cChave. E será retornado se a chave
foi encontrada ou não (.T. ou ,F,). Neste caso não é necessário passar a filial. Ela será inserida
automaticamente na chave de pesquisa pela função.
Nos relatórios devemos analisar que a função “SetPrint”, possibilita efetuar filtros , escolha da ordem e
geração em disco ou impressora , no final dos programas de relatório devemos restaurar a ordem
original do arquivos e limpar o filtro e desativar a impressora.
//Término do relatorio
dbSelectArea("SRA")
Set Filter to
dbSetOrder(1)
If aReturn[5] = 1
Set Printer To
86
Commit
ourspool(wnrel)
Endif
MS_FLUSH()
Ou t ros Cuidados
Um dos cuidados que devemos ter quando da criação de relatórios contendo valores é a utilização dos
subtotais e totais, a fim de evitar erros que podem ser desastrosos durante uma tomada de decisão
errada devido a valores errados.
A utilização de somatórias deve ser bastante criteriosa a fim de não cometermos o erro de misturarmos
unidades de medidas diferentes no mesmo cálculo.
Quando elaboramos um sistema, existem muitos relatórios que geram dados para outros relatórios e
consultas.
Devemos tomar cuidado para que não aconteçam divergências de informações de um para o outro, como
por exemplo, no caso de valores.
Um bom exemplo disso, é a rotina de impressão de folha de pagamento. Este relatório exibe informações
que são utilizadas em outros relatórios, tais como, valores para o FGTS, guia de recolhimento de
impostos.
Uma solução para que não se ocorra uma divergência de valores, seria utilizar uma única função ou rotina
de processamento. Isto evitaria que ao se alterar o sistema, por motivo de lei ou outro qualquer, o
programador alterasse por exemplo às rotinas de relatório de folha de pagamento e guia de impostos e
esquecesse de alterar por exemplo à rotina de relatório de FGTS.
Exemplos como Saldos Bancários, Quantidades de Estoques, Valores de Faturamento, entre outros, devem
ser confrontados entre relatórios e consultas para não gerarem informações errôneas ao cliente.
Normalmente estes problemas ocorrem em funções de critérios de filtragens diferenciados entre eles. Para
evitar este tipo de problema é fundamental que o analista ao efetuar alguma manutenção em algum
relatório ou consulta atente-se ao fato de assegurar que esta alteração não influencie outras situações.
Este é um tipo de não conformidade simples de ser evitada e que pode causar problemas sérios para os
usuários além de ser de dificil argumentação quando nos questionado, pois evidencia falta de atenção ou
critério na manuteção ou falta de conhecimento sobre o funcionamento do sistema.
O Protheus utiliza a tecnologia Cliente/Servidor. Isto significa que o aplicativo não é mais executado
individualmente em cada máquina, ele será executado no servidor do aplicativo. Até a versão 4.07 um
programa travado significava que apenas a estação estava comprometida (o executável estava na
memória da estação). Com o Protheus, todo o processamento está no Server e quando o programa está
em looping estaremos gradativamente “usando todo a CPU do Server” e consequentemente parando todo
o processamento.
Se ao desenvolvermos uma rotina e a mesma entrar em looping (tiver apenas uma entrada e não tiver
uma saída do processamento), este processamento utilizará todos os recursos do servidor
comprometendo (reduzindo drasticamente a performance do aplicativo), ou até impedindo, o uso do
aplicativo por todos os demais usuários.
87
Se isso acontecer em uma empresa onde existem apenas 5 usuários, o administrador da rede poderá
reiniciar o servidor, porém onde existe um número considerável de usuários poderá haver um prejuízo
para a empresa que utiliza nosso sistema.
Exemplo:
dbSeek(xFilial(“SE1”)+DTOS(dDtIni))
Do While SE1->(!Eof())
Enddo
No exemplo acima, a rotina ficará em looping (pois falta um comando de saída da rotina, um DbSkip()
seria o mais apropriado), utilizando todos os recursos de processamento do servidor, fazendo com que o
mesmo pare de funcionar.
Outro exemplo:
aCampos := {}
Do while .T.
Aadd(aCampos, “Teste”)
Enddo
No exemplo acima o caso é ainda mais crítico, pois além utilizar todo o recurso de processamento do
servidor, em dado momento haverá uma queda do aplicativo, devido a limitação da variável tipo
Array, criada acima. E quando este limite for ultrapassado, o sistema será interrompido abruptamente
e todos os demais usuários ficarão impossibilitados de utilizarem o sistema.
O editor de texto Word da Microsoft, os arquivos de imagens (BMP,JPEG,etc) exigem um lugar físico para
abertura dos documentos/imagens, navegando pela Internet por exemplo são copiados via conexão para
um diretório temporário no computador para serem visualizados.
O AP5 trabalha da mesma forma, através dessas considerações e utilizando a arquitetura Client/Server via
conexão os arquivos serão copiados.
Os arquivos que poderão ser copiados deverão estar necessariamente embaixo do RootPath na
configuração do Server, isto é, o diretório DOCS do exemplo abaixo deverá ser sub-diretório do RootPath.
88
CPYS2T("\DOCS\EXEMPLO.DOC,"C:\WINDOWS\TEMP",.T.)
2o. é o <Nome do Diretório> do Client e/ou local físico onde será copiado o arquivo.
CPYT2S("C:\WINDOWS\TEMP\EXEMPLO.DOC,"\DOCS",.T.)
As funções possuem um retorno True(.T.) ou False(.F.) indicando se a cópia foi realizada com sucesso ou
não.
Desenvolvendo Telas
A aparência e objetividade das telas num sistema é base fundamental da interface Sistema x Usuário.
O AP5 já cria, automaticamente, a grande parte das telas de um módulo, tais como a Browse, a GetDados
e Enchoice.
Algumas outras telas necessitam de construção “manual”, ou seja, com a utilização de comandos, tais
como “SAY” , “GET” e “LABEL”, na Dialog.
Procure sempre colocar em tela as informações que mais se objetivam com o assunto abordado.
Sempre que possível, dê preferência aos campos obrigatórios primeiro. Isso facilita a digitação do usuário,
que não precisará passar de campo em campo (no caso de estar utilizando a tecla <TAB>) até chegar ao
campo desejado. A ordem dos campos também é importante para a fácil localização das informações.
Quando o volume de informações é muito grande, divida os campos em folders, ou seja, pastas,
agrupando os campos em assuntos. Isso irá deixar a tela menos poluída e evitará que o usuário navegue
por uma tela só. Para fazer essa facilidade, preencha o campo X3_FOLDER, no SX3, com um número,
agrupando-os de acordo com a tipo de informação e no SXA, com o ALIAS do arquivo em pauta, a ordem,
que equivale ao numero informado no X3_FOLDER e a descrição nos três idiomas. Essa descrição que será
a informação contida na pasta do folder. Exemplo: Os campos SZ1_ENDER, SZ1_NUM e SZ1_BAIRRO
devem estar com o campo X3_FOLDER preenchido com o conteúdo “1”. No SXA, o XA_ALIAS deverá ser
SZ1, o XA_ORDEM = “1” (mesmo valor preenchido no X3_FOLDER), no XA_DESCRIC, “Endereço
Residencial” e, nos demais, o mesmo texto em outros idiomas.
O Folder, além de agrupar e facilitar a procura pelos campos, evita a rolagem vertical da tela, facilitando a
visualização das informações.
Evite tela com muitos botões. Isso poderá confundir o usuário e induzi-lo ao erro. Utilize telas sequenciais,
conhecidas como Wizard (semelhante aos de instalação de um software). Dessa forma, o usuário ficará
89
mais atento aos fatos, dificultando o erro. Mas cuidado: não faça disso uma incansável sequência de telas,
pois isso acabará desmotivando o usuário a utilizar o sistema.
Enfim, as telas devem ser limpas e objetivas, de tal forma que impeça o usuário de sair de seu objetivo
final. Todo curioso irá apertar todos os botões da tela ou preencher todos os campos com qualquer tipo de
informação. Portanto, esteja atento a tamanho dos labels, para que os mesmos não excedam o tamanho
da caixa de diálogo definida. Isso, além de não ser estético, prejudica o entendimento da informação.
Quando temos Janelas que necessitem apresentar mais de uma getdados, devemos salvar os elementos,
acols, aheader e n, da tela anterior para apresentar uma nova janela.
Getdados
aColsAnt := aClone(Acols)
aHeaderAnt := aClone(aHeader)
nElemAnt := n
E para restaura-las:
aCols := aClone(aColsAnt)
aHeader := aClone(aHeaderAnt)
n := nElemAnt
Deixar o sistema flexivél , pois isso permite uma grande variedade de desenvolvimento pelos nossos
analistas de suporte de acordo com a necessidade de cada tipo de cliente/implantação.
Permitir que o sistema seja o mais abrangente possível de acordo com cada tipo de segmento de negócio.
O ponto de entrada tem resultado quando permite que um processo possa ser modificado, desde que ele
não seja crítico para o sistema.
90
Ele é útil em processos que podem ser diferentes de acordo com o tipo de negócio de cada empresa ou
estratégia adotada.
Function TMKA010()
If lTMKMCL
Endif
Return( lRetorno )
Avaliar com critério a criação do Ponto de Entrada, pois é importante localiza-lo num ponto que seja útil,
não redudante e que realmente dê condições de atender ao solicitante.
O Ponto de entrada não é uma ferramenta de correção de eventuais falha do sistema e sim para ajudar no
desenvolvimento de negócios específicos.
Documentar no QUARK com nome,momento no qual o momento em que ele é disparado, parametros que
ele envia,retorno esperado (se houver) e o que ele executa com o retorno.
Con tabilizando
A contabilização de registros em um sistema ERP é necessário toda vez que houverem operaçoes
envolvendo valores na empresa, como por exemplo, a emissão de uma nota fiscal, um recebimento de
dinheiro, um pagamento na folha, entre outros.
Para quem está programando é fundamental que este conceito esteja bastante sidimentado.
• Definir
os lançamentos padronizados que serão utilizados para a rotina (cada módulo ou família de
módulo possui uma sequencia lógica)
91
Existem três funções que deverão ser utilizadas, para que seja criado um arquivo texto, contendo as
informações a serem contabilizadas.
Como temos 2 sistemas contábeis (SIGACON e SIGACTB) com procedimentos diferenciados programamos
de forma identica para ambos porém internamente as rotinas efetuam comandos diferentes. Os comandos
para a contabilização são :
A Função HeadProva
Este função cria o cabeçalho da contabilização. É tratada de forma diferenciada para os módulos SIGACON
e SIGACTB.
Sintaxe:
Onde:
NHdlPrv -> Variável que conterá o num. (Handle) do arquivo (.LAN) criado.
A f unção DetProva( )
Em primeiro lugar, deve-se estar posicionado no registro, que contém o valor à ser contabilizado
Sintaxe:
ExpN1 := DetProva(ExpN2,ExpC1,ExpC2,ExpC3)
A f unção RodaProva( )
Sintaxe:
RodaProva(ExpN1, ExpN2)
No Final, ou seja, após todos registros serem processados utilizar a função CA100INCL(), cujo objetivo é
ler o arquivo gerado (.LAN), e gerar os lançamentos no arquivo SI2 (Lançamentos contábeis).
Exemplo:
92
Onde:
At ualizando SX (ATUSX)
O ATUSX é uma ferramenta muito importante utilizada na manutenção dos arquivos customizadores
internos: os arquivos SX’s . É nos arquivos SX que estão armazenadas todas as informações padrões
necessárias para a criação de bases das empresas e efetuar possíveis customizações.
Em uma atualização de versão, o sistema irá fazer uma compatibilização de dados com os arquivos já
existentes e os atualizará com base nos SX’s. Ao desenvolver uma rotina que exige um novo campo, por
exemplo, este deverá ser criado no ATUSX, caso contrário gerará uma não conformidade
comprometendo todo o trabalho da atualização e o bom andamento do trabalho. Todo os campos,
perguntas, índices, parâmetros novos deverão estar no ATUSX , pois estes são os padrões do Protheus.
É aqui também que cadastramos os HELP’s de campo e de programas, criamos os menus do sistema e
onde disponibilizamos informações para serem traduzidas para outros países.
Criação de Índice no Cadastro de Funcionários- Suponhamos que seja necessário um índice por Data de
Admissão. Neste caso utilizaremos o SINDEX , onde deverão ser alimentados basicamente o Alias (SRA),
a ordem , a chave de indexação (RA_ADMISSA) e sua descrição em Português. As descrições referentes
às outras línguas deverão ficar a cargo do departamento de traduções. Numa atualização de versão, o
sistema enxergará a existência deste índice pelo SINDEX e o disponibilizará para utilização.
Ao final da manutenção dos arquivos SX’s, abre-se uma janela onde deve ser documentado todas as
alterações efetuadas da forma mais clara e precisa possível. Esta documentação é de extrema importância
para que se tenha um controle dos arquivos customizadores padrões e garantem um perfeito
funcionamento do Protheus.
Esta tabela contém as perguntas, os valores armazenados e a última resposta utilizada para
processamento, impressão de relatórios , etc.
Todos os processamentos ou relatórios que tenham a opção de parametrização, deverão utilizar a função
Pergunte para carregar os valores dos parâmetros e/ou apresentar na tela as perguntas relacionadas.
Como o usuário pode não utilizar a opção de parametrização, devemos sempre carregar as variáveis
MV_PARXX com os valores default ou com as últimas respostas aplicadas, para evitar erros de
comparação de variáveis.
93
Armazena os Paths dos arquivos possibilitando que estes possam ser distribuídos em diversos drives ou
diretórios.
Elemento chave para a execução de um processamento, que determina diferentes resultados dependendo
do seu conteúdo.
Armazena sequencias alfanuméricas que deverão ser controladas por um semáforo. Um exemplo clássico
seria a numeração de pedidos de venda, em que vários usuários poderiam estar utilizando o mesmo
número de pedido.
O q ue é
Tratando-se de Banco de Dados, toda e qualquer operação de inclusão, alteração ou exclusão de registro
é armazenada primeiramente na área de LOG, garantindo assim que ao fazer a inclusão de uma linha
(registro) seja garantida a inclusão completa de todas as colunas (campos). Caso não seja possível a
inclusão da linha completa ele executa um procedimento chamado de ROLLBACK, ou seja, ignora todo o
registro.
Quando usar
Quando temos uma operação em Banco de Dados que necessite que várias inclusões, alterações ou
exclusões só sejam efetuadas quando todas as operações tenham sido realizadas com sucesso, garantindo
com isso que não seja atualizada parcialmente uma tabela ou que atualize uma tabela e não atualize outra
tabela relacionada.
Com o usar
94
Para definir uma transação, deve-se utilizar os comandos BEGIN TRANSACTION e END TRANSACTION
para definir inicio e fim de uma transação respectivamente. Todas informações à serem gravadas no
Banco devem estar dentro de uma única transação sejam elas provenientes de uma ou várias tabelas.
Deve-ser evitar utilizar laços (WHILE, FOR) dentro de uma transação, pois a área de LOG do banco é
limitada, e se o volume de informações ultrapassarem este limite, ocasionará o travamento do banco de
dados. O tamanho da transação deve-ser ser conhecido pelo programdor. Em suma, para exemplificar,
devemos controlar a transação de uma nota e não de um conjunto ilimitado de notas.
O controle de transação jamais deverá ser utilizado durante processo que envolvam interface (telas com
entrada de dados). O controle deve-se resumir apenas ao processo de gravação. Entre um início de
transação (Begin Transaction) e um final (End Transaction) Todos os registros a serem gravados ficam
“locados” até o final da transação. Caso tenhamos uma tela após o BEGIN e antes do END dependeremos
do usuário para efetuar a liberação da transação, fato este que causaria enormes problemas para o
usuário.
Outro lugar que não deve-se ter o controle de transação refere-se a rotinas de reprocessamentos ou
recálculos, onde as informações podem ser regerados durante este processo ou onde possamos ter um
grande número de locks.
BEGIN TRANSACTION
ExpN1 :=FuncGrava()
END TRANSACTION
Caso exista uma transação dentro de uma outra a segunda será automaticamente ignorada, fechando-se
a transação principal quando da chamada do comando END TRANSACTION.
Estes comandos são traduzidos, analisados e modificados antes que o compilador comece a trabalhar para
gerar um arquivo objeto. O responsável por esta tradução é o pré-processador que é um tradutor
inteligente que atua antes da geração do código objeto.
Em sua maioria, isto se resume a encontrar os comandos no código fonte e traduzi-los para instruções e
funções equivalentes que se acham no corpo da função ou no conteúdo de arquivos .CH (arquivos de
cabeçalho). Este tipo de arquivo (.CH), contém diversos comandos que serão utilizados por todas as
funções que contenham a instrução “include” em seu código.
Estes mesmos comandos poderiam estar embutidos na função, mas para facilitar a manutenção, um único
arquivo .CH, pode ser incluído (comando include) em várias funções ao mesmo tempo. Não há a
necessidade de colocar o comando include em cada função. Uma única menção ao .CH no arquivo .PR?,
servirá ao propósito de todas as funções nele embutidas.
Estes comandos são diretivas do pré-processador e começam sempre com o caracter “#” diretamente à
sua frente e devem estar escritos em caracteres tipo caixa alta. Os mais utilizados no Protheus são:
#DEFINE
#IFDEF, ou #IFNDEF
#ELSE
95
#ENDIF
#INCLUDE
Cada um destes comandos pode ser colocado em qualquer parte do arquivo fonte, que será lido pelo pré-
processador. No entanto, para facilitar a visualização da existência destes comandos e manutenção da
função, estes comandos devem ser colocados no início do fonte.
O pré-processador substituirá, cada ocorrência da constante no fonte, será substituída pela expressão ou
valor, que estiver contida diretamente à frente da mesma. A exemplo de sintaxe e código fonte para este
comando é:
#DEFINE _TESC 27
if _nLastkey == _TESC
RETURN
Endif
if _LESC == _TESC
RETURN
Endif
Esta diretiva é muito útil quando temos um valor constante várias vezes repetido dentro do código fonte,
que poderá ser alterado com freqüência no decorrer da vida útil da função.
<instruções>
#ELSE
<outras instruções>
#ENDIF
Esta diretiva do pré-processador permite que você prepare aplicações para compilação condicional, ou em
outras palavras, se a <constante>, definida anteriormente via diretiva DEFINE ou pelo Protheus foi
definida (IFDEF), as <instruções> serão incorporadas ao código objeto e as <outras instruções>, serão
desprezadas. Mas se a <constante> não foi definida <IFNDEF> as <instruções> serão incorporadas e as
<outras instruções> serão desprezadas.
#INCLUDE “<ARQUIVO>”
Uma instrução INCLUDE diz ao pré-processador para inserir o conteúdo de outro arquivo em um local
determinado dentro da função. Este arquivo especificado, deve focalizar outras instruções do pré-
processador que possam ser comuns a diversos módulos da rotina.
Uso de St rings
Para que o sistema possa ser utilizado em outros países com línguas diferentes ao invés de inserirmos
diretamente os textos no fonte do relatório utilizamos o recurso de strings, onde através de um include
acessaremos o texto em três línguas diferentes (Português, Espanhol e Inglês) dependendo da forma da
compilação.
É convencionado que o nome do include seja o mesmo nome do fonte do relatório para que a manutenção
deste relatório seja o mais simples possível.
Exemplo:
96
Este tratamento é feito internamente através dos campo XX_FILIAL obedecendo a seguinte regra:
Quando o arquivo esta configurado para trabalhar no modo compartilhado (X2_MODO = ‘C’), este campo
será gravado com “ “ ( espaços ).
Arquivos Exclusivos
Quando o arquivo esta configurado para trabalhar no modo exclusivo ( X2_MODO= ‘C’ ), esta campo será
gravado com o código da Filial Atual.
Deste modo o registro focara disponivel apenas para a Filial que o gravou.
Para que o registro realmente fique disponível ou não para suas respectivas Filiais , TODAS as rotinas que
manilpulam registros diretamente na base de dados deverá verificar a Filial através da Função xFilial() ,
alem disto a maioria dos índices possuem o campo FILIAL na
chave :
A função xFilial() verifica se o arquivo é exclusivo ou compartilhado e ira retornar “ “ se o arquivo for
Compartilhado e o código da Filial se o arquivo for exclusivo .
Por exemplo :
DbSelectArea(“SA1”)
DbSeek(xFilial(“SA1”)+cCodCli+cLoja)
Índice do SA1 :
A1_FILIAL+A1_COD+A1_LOJA
Ou um processamento no arquivo :
Sendo o campo FILIAL parte da chave de Todos os índices do sistema, este procedimento garante que a
utilização dos registros será exclusiva da Filial que criou os mesmos no caso do arquivo ser Exclusivo, ou
disponível para todas as Filiais quando o mesmo estiver configurado como Compartilhado.
97
Jamais use um campo filial de uma tabela para executar um dbSeek() em outra tabela. Pois uma tabela
poderá ser compartillhada (campo filial em branco), enquanto que a outra poderá ser compartilhada
(campo filial preenchido).
A variável cFilAnt contém a filial que o usuário está operando, e a variável cEmpant contém a empresa e
a filial
Nos sistemas Microsiga, a filtragem dos dados em ambiente Code Base os “DBFs” é feita de maneira
geral pela Função INDREGUA(Params,) , o que de forma geral não impede o uso de instruções como SET
FILTER TO, DBSETFILTER(), DBFILTER() ou qualquer outro comando de sintaxe xBase. A INDREGUA() é
uma função interna que reúne vários atrativos e facilidades para o seu uso, entre elas a possibilidade de
se indexar e filtrar os registros através dos parâmetros fornecidos, ela também é preferencialmente usada
para que o código fique mais “limpo” e de fácil interpretação pois dentro de sua estrutura reúne uma série
de comandos de indexação e filtragem que agiliza o processo de criação de índices e filtros em arquivos
de trabalho com menos linhas de código, vejamos o Exemplo :
Sua função é garantir unicidade. Em toda relação, por definição, tem-se uma ou mais chaves candidatas.
Dessas chaves, uma será primária e se houver mais de uma na relação, essas outras serão definidas
como chave alternada.
É um atributo cuja função é permitir relacionamento. Em uma tabela na qual o atributo é chave externa
ou estrangeira, em outra, o atributo deve ser chave primária, e os valores dos campos são necessários.
Todos os valores da chave estrangeira tem, obrigatoriamente, que ter valor correspondente na chave
primária que se relaciona; mas nem todos os valores encontrados na chave primária, precisam ter seus
correspondentes na chave estrangeira que se relaciona. Por exemplo, na tabela de clientes, o campo
A1_COD (código do cliente), vai estar relacionado com outra tabela que indica quais são os pedidos de
venda colocados. Desta forma, nem todos os clientes precisam ter pedidos de venda colocados; mas,
necessariamente, todos os pedidos de venda precisam de um cliente.
Como o PROTHEUS foi projetado para o ambiente SQL, onde a integridade referencial das tabelas é
definida no próprio banco de dados através de regras internas, devemos tomar algumas precauções com
esse tópico:
Verificar a integridade da coluna em todas as tabelas relacionadas: não pode-se alterar o tamanho do
código do cliente em apenas uma tabela, caso esse código seja alterado deve-se verificar as tabelas de
cabecalho e itens das notas fiscais, de titulos a pagar e receber, etc. O sistema conta com o recurso de
grupos de tabelas relacionadas, que permite alterar o tamanho de diversas colunas de uma vez só ,
garantindo a integridade das colunas
Verificar a integridade dos cadastros com todas as tabelas relacionadas: não pode-se excluir o código do
cliente se existe um pedido de vendas em aberto para esse cliente, deve-se verificar todas as tabelas
relacionadas antes de atualizar a base de dados.Além disso na inclusão de cadastros devemos utilizar as
funções existchav e existcpo para garantir que as informações de chave não sejam repetidas e que o
acesso a tabelas externas seja validado de maneira consistente.
98
atualizar o arquivo de saldos por localização, etc. Deve-se fazer um estudo antes de qualquer alteração
em atualização de base de dados.
Tome como exemplo o MATA250.PRX . O vetor aRotAuto é passado para o programa citado. Se este vetor
contiver elementos, significa que será utilizada a Rotina Automática. Este vetor deve, quando da
utilização das rotinas automáticas, conter os dados mínimos necessários para a atualização dos arquivos.
Onde
Observação: A Validação pode ser uma função ou um valor ‘NIL’. Se for ‘NIL’, as validações a serem
utilizadas para o respectivo campo serão as existentes no SX3. Se as validações não forem as do SX3,
elas devem ser passadas numa função.
Exemplo,
{ "D3_QUANT" ,1 ,NIL } , ;
Para o processo de inclusão simples, sem getdados, a variável padrão a ser utilizada nos programas
chama-se aRotAuto, e para processo de inclusão com cabeçalho e itens, as variáveis a serem utilizadas
são: aAutoCab para o cabeçalho, e aAutoItens para os itens da getdados.
Para uma inclusão simples, tomar como exemplo o MATA250.PRX. Para uma inclusão com cabeçalho e
ítem, tomar como exemplo o CONA050.PRX.
99
O controle de Semaforo permite que o sistema controle a Numeração Automática de Documentos On Line.
Temos basicamente 3 funções que gerenciam o controle do mesmo.
São elas :
ROLLBACKSXE -> Descarta o número pendente do semáforo. É usado quando o usuário cancela a
operação (o numero não é aproveitado).
CONFIRMSXE -> Confirma o número sugerido. Esta função deve ser chamada quando da confirmação da
gravação do registro.
MAYIUSE -> Checa fisicamente se um determinado arquivo existe. O arquivo poderá conter o número
sequencial.
At ualização do SourceSafe
A atualização do Source Safe é a última, e mais crítica, etapa do processo de alteração dos programas.
Para que ela seja feita com a máxima segurança algumas etapas devem ser observadas. A seguir:
Após as alterações será necessária uma análise meticulosa de tudo o que foi alterado para avaliar qual o
impacto que estas poderão causar no programa em que foram executadas e nos programas
correlacionados;
Deverão ser efetuados o maior número de testes onde deverão ser previstos o maior número de situações
possíveis e prováveis. Os testes deverão ser simulados em base equivalente à instalada no cliente e para
as novas versões, em uma nova base que poderá ser gerada através do ATUSX;
Feita a análise, os testes e antes de atualizar definitivamente o Source Safe o programa alterado deverá
ser comparado com o constante no Source Safe para verificar se as alterações foram realmente feitas no
programa que foi reservado e, só então o programa poderá ser “Baixado”.
Após a “Baixa”, e para garantir que o atualização do Source Safe foi feita corretamente, o programa
atualizado deverá ser novamente comparado. E é claro que se todas as etapas anteriores, principalmente
a 1 e 2 , foram cumpridas essa não passará de uma medida de segurança.
A fim de evitar os inconvenientes citados no ponto anterior, existem procedimentos que devem ser
adotados no nosso dia a dia e repassado para aqueles funcionários que se acoplam a nossa equipe. Estes
são (entre parêntesis os problemas que seriam reduzidos usando os procedimentos) :
• Quando é incluído um novo STR em um CH, ou criado um novo CH, ou modificado um STR em um
CH já existente, este deve ser replicado em PORTUGUÊS para os demais idiomas e
automaticamente deve ser encaminha um e-mail para [email protected] indicando
a versão, o STR e o CH que foi alterado.
100
• Quando criado ou alterado um novo HELP (de campo ou de programa) deve ser informado de
imediato para traduções para proceder a tradução para os outros idiomas.
• Para atualizar um parâmetro deve ser sempre usada a função PUTMV, NUNCA DEVE SER
PREENCHIDO NEM POSICIONADO POR FORA. Esta função atualiza nos três idiomas.
• Quando criado um campo novo “similar” a outros já existentes no sistema, deve se analisar se este
deve ser replicado com características diferentes para todos os paises localizados, ou se as
características devem ser igual independentemente da localização. Na falta de “critério” ou
informação, deve ser informado ao setor de localizações.
• Quando criado um campo novo de uso exclusivo de Brasil (E1_INSS por exemplo) deve ser
informada a equipe de localizações para configurar este campo (uso, browse, etc.) de acordo com
os demais paises.
• Quando for modificada a característica de um campo do sistema e este estiver replicado para o
resto dos países, as alterações devem ser replicadas em todos os paises. Na dúvida da
aplicabilidade da alteração nos outros paises, deve ser informada a equipe de localizações.
• Os novos campos tipo COMBO, devem ser criados com numeração e não com siglas (1 para sim e 2
para não, ao invés de S para sim e N para não). Esta alteração o inclusão deve ser informada de
imediato para a equipe de traduções.
• Quando for criado um novo parâmetro, ou modificado o conteúdo default de um já existente, esta
modificação deve ser aplicada nas 3 línguas.
• Quando houve a possibilidade de pegar um STR do dicionário (função RETTITLE() ), este deve ser
pego, o que evita ter que criar vários STR e tratarmos com a variável cPaisLoc dentro do
programa. Exemplo CGC, NOTA FISCAL, CEP, etc.
• Quando criadas novas perguntas no SX1, ou modificadas as existentes, e o X1_GSC for igual a C,
deve ser informado de imediato para traduções, pois os campos das opções do combo, quando
vazias, geram erro fatal na execução.
Caso exista alguma entrada de dados que seja possível ser assumida qualquer valor apenas no schedule
deve-se adotar o seguinte procedimento :
Usar a variável __cInternet, que se estiver com valor .T. (Verdadeiro) estamos no processo de schedule.
101
Modelo 1
Este modelo de programa exibe um Browse vertical de campos presentes no dicionário de dados.
Genericamente as validações são herdadas do próprio dicionário de dados.
/*/
+---------------------------------------------------------------------------+
+ Funcao | FINA010 | Autor | Wagner Xavier | Data | 28/04/92 |
+-----------+----------+-------+-----------------------+------+-------------+
| Descricao | Programa de atualizacao de Naturezas |
+-----------+---------------------------------------------------------------+
| Sintaxe | FINA010() |
+-----------+---------------------------------------------------------------+
| Uso | Generico |
+---------------------------------------------------------------------------+
| ATUALIZACOES SOFRIDAS DESDE A CONSTRUCAO NICIAL |
+-----------+--------+------+-----------------------------------------------+
|Programador| Data | BOPS | Motivo da Alteracao |
+-----------+--------+------+-----------------------------------------------+
| | | | |
+-----------+--------+------+-----------------------------------------------+
/*/
102
#INCLUDE "FINA010.CH"
#INCLUDE "PROTHEUS.CH"
FUNCTION FINA010
/*/
+----------------------------------------------------------------+
| Define Array contendo as Rotinas a executar do programa +
| ----------- Elementos contidos por dimensao ------------ +
| 1. Nome a aparecer no cabecalho +
| 2. Nome da Rotina associada +
| 3. Usado pela rotina +
| 4. Tipo de Transacao a ser efetuada +
| 1 - Pesquisa e Posiciona em um Banco de Dados +
| 2 - Simplesmente Mostra os Campos +
| 3 - Inclui registros no Bancos de Dados +
| 4 - Altera o registro corrente +
| 5 - Remove o registro corrente do Banco de Dados +
+----------------------------------------------------------------+
/*/
PRIVATE aRotina := { { OemToAnsi(STR0001) ,"AxPesqui", 0 , 1},; //"Pesquisar"
{ OemToAnsi(STR0002) ,"AxVisual", 0 , 2},; //"Visualizar"
{ OemToAnsi(STR0003) ,"AxInclui", 0 , 3},; //"Incluir"
{ OemToAnsi(STR0004) ,"AxAltera", 0 , 4},; //"Alterar"
{ OemToAnsi(STR0005) ,"FA010Del", 0 , 5, 3} } //"Excluir"
+----------------------------------------------------------------+
| Define o cabecalho da tela de atualizacoes |
+----------------------------------------------------------------+
PRIVATE cCadastro := OemToAnsi(STR0006) //"Atualizacao de Naturezas"
+----------------------------------------------------------------+
| Endereca funcao Mbrowse |
+----------------------------------------------------------------+
mBrowse( 6, 1,22,75,"SED")
Return
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |FA010DEL | Autor | Wagner Xavier | Data | 8/04/92 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Programa de exclusao de Naturezas |
+------------+-----------------------------------------------------------+
| Sintaxe | A010Deleta(ExpC1,ExpN1,ExpN2) |
+------------+-----------------------------------------------------------+
| Parametros | ExpC1 = Alias do arquivo |
| | ExpN1 = Numero do registro |
| | ExpN2 = Numero da opcao selecionada |
+------------+-----------------------------------------------------------+
| Uso | FINA010 |
+------------+-----------------------------------------------------------+
/*/
FUNCTION FA010DEL(cAlias,nReg,nOpc)
Local aAC := { OemToAnsi(STR0007),OemToAnsi(STR0008) } //"Abandona"###"Confirma"
Local bCampo
Local lDeleta := .T.
Local oDlg
Local nCont
Local nOpca
+----------------------------------------------------------------+
| Monta a entrada de dados do arquivo |
+----------------------------------------------------------------+
Private aTELA[0][0],aGETS[0]
+----------------------------------------------------------------+
| Verifica se o arquivo esta realmente vazio ou se esta |
| posicionado em outra filial |
+----------------------------------------------------------------+
If EOF() .or. SED->ED_FILIAL != xFilial("SED")
HELP(" " , 1 , "ARQVAZIO")
Return Nil
Endif
While .T.
+----------------------------------------------------------------+
| Envia para processamento dos Gets |
+----------------------------------------------------------------+
103
dbSelectArea( cAlias )
bCampo := {|nCPO| Field(nCPO) }
FOR nCont := 1 TO FCount()
M->&(EVAL(bCampo,nCont)) := FieldGet(nCont)
NEXT nCont
nOpca := 1
DEFINE MSDIALOG oDlg TITLE cCadastro FROM 9,0 TO 28,80 OF oMainWnd
EnChoice( cAlias, nReg, nOpc, ,"AC",OemToAnsi(STR0009) ) //"Quanto a exclusao?"
ACTIVATE MSDIALOG oDlg ON INIT EnchoiceBar(oDlg, {|| nOpca := 2,oDlg:End()},;
{|| nOpca := 1,oDlg:End()})
DbSelectArea(cAlias)
dbSelectArea(cAlias)
IF nOpcA == 2
+----------------------------------------------------------------+
| Antes de deletar, verificar se existe movimentacao |
+----------------------------------------------------------------+
dbSelectArea("SE1")
dbSetOrder(3)
IF (dbSeek(cFilial+SED->ED_CODIGO))
Help(" ",1,"A010NAODEL")
lDeleta := .F.
MsUnlock()
Else
dbSelectArea("SE2")
dbSetOrder(2)
IF (dbSeek(cFilial+SED->ED_CODIGO))
Help(" ",1,"A010NAODEL")
lDeleta := .F.
MsUnlock( )
Else
dbSelectArea("SE5")
dbSetOrder(4)
IF (dbSeek(cFilial+SED->ED_CODIGO))
Help(" ",1,"A010NAODEL")
lDeleta := .F.
MsUnlock( )
Endif
Endif
Endif
If lDeleta
+----------------------------------------------------------------+
| Inicio da Protecao via TTS |
+----------------------------------------------------------------+
BEGIN TRANSACTION
dbSelectArea(cAlias)
RecLock(cAlias,.F.,.T.)
dbDelete()
END TRANSACTION
+----------------------------------------------------------------+
| Final da protecao via TTS |
+----------------------------------------------------------------+
Endif
Else
MsUnlock( )
Endif
Exit
Enddo
dbSelectArea("SE1")
dbSetOrder(1)
dbSelectArea("SE2")
dbSetOrder(1)
dbSelectArea("SE5")
dbSetOrder(1)
dbSelectArea(cAlias)
RETURN
Modelo 2
104
Este modelo de programa exibe um cabeçalho com informações pré-determinadas, um Browse horizontal
central (dependente do dicionário de dados) e um rodapé com variáveis de memória que são atualizadas
de acordo com os valores preenchidos no Browse horizontal.
/*/
+---------------------------------------------------------------------------+
+ Funcao | CTBA120 | Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+-----------+----------+-------+-----------------------+------+-------------+
| Descricao | Cadastro de Criterios de Rateio Externo |
+-----------+---------------------------------------------------------------+
| Sintaxe | CTBA120() |
+-----------+---------------------------------------------------------------+
| Uso | Generico |
+---------------------------------------------------------------------------+
| ATUALIZACOES SOFRIDAS DESDE A CONSTRUCAO NICIAL |
+-----------+--------+------+-----------------------------------------------+
|Programador| Data | BOPS | Motivo da Alteracao |
+-----------+--------+------+-----------------------------------------------+
| | | | |
+-----------+--------+------+-----------------------------------------------+
/*/
#INCLUDE "CTBA120.CH"
#INCLUDE "PROTHEUS.CH"
#INCLUDE "FONT.CH"
105
FUNCTION CTBA120()
/*/
+----------------------------------------------------------------+
| Define Array contendo as Rotinas a executar do programa +
| ----------- Elementos contidos por dimensao ------------ +
| 1. Nome a aparecer no cabecalho +
| 2. Nome da Rotina associada +
| 3. Usado pela rotina +
| 4. Tipo de Transacao a ser efetuada +
| 1 - Pesquisa e Posiciona em um Banco de Dados +
| 2 - Simplesmente Mostra os Campos +
| 3 - Inclui registros no Bancos de Dados +
| 4 - Altera o registro corrente +
| 5 - Remove o registro corrente do Banco de Dados +
+----------------------------------------------------------------+
/*/
PRIVATE aRotina := { { OemToAnsi(STR0001),"AxPesqui", 0 , 1},; //"Pesquisar"
{ OemToAnsi(STR0002),"Ctb120Cad", 0 , 2},; //"Visualizar"
{ OemToAnsi(STR0003),"Ctb120Cad", 0 , 3},; //"Incluir"
{ OemToAnsi(STR0004),"Ctb120Cad", 0 , 4},; //"Alterar"
{ OemToAnsi(STR0005),"Ctb120Cad", 0 , 5} } //"Excluir"
+----------------------------------------------------------------+
| Define o cabecalho da tela de atualizacoes |
+----------------------------------------------------------------+
Private cCadastro := OemToAnsi(STR0006) //"Criterios de Rateio
+----------------------------------------------------------------+
| Endereca funcao Mbrowse |
+----------------------------------------------------------------+
mBrowse( 6, 1,22,75,"CTJ" )
Return
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |CTB120CAD| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Cadastro de Rateio Externo |
+------------+-----------------------------------------------------------+
| Sintaxe | Ctb120Cad(ExpC1,ExpN1,ExpN2) |
+------------+-----------------------------------------------------------+
| Parametros | ExpC1 = Alias do arquivo |
| | ExpN1 = Numero do registro |
| | ExpN2 = Numero da opcao selecionada |
+------------+-----------------------------------------------------------+
| Uso | CTBA120 |
+------------+-----------------------------------------------------------+
/*/
Function Ctb120Cad(cAlias,nReg,nOpc)
Local aSaveArea := GetArea()
Local aCampos := {}
Local aAltera := {}
Local aTpSald := CTBCBOX("CTJ_TPSALD")
Local cArq
Local cRateio
Local cDescRat
lOCAL cMoedaLc
Local cTpSald
Local nOpca := 0
Local oGetDb
Local oDlg
Local oFnt
Local oTpSald
Private aTela := {}
Private aGets := {}
Private aHeader := {}
Private nTotalD := 0
Private nTotalC := 0
+----------------------------------------------------------------+
| Monta aHeader para uso com MSGETDB |
+----------------------------------------------------------------+
aCampos := Ctb120Head(@aAltera)
+----------------------------------------------------------------+
| Cria arquivo Temporario para uso com MSGETDB |
106
+----------------------------------------------------------------+
Ctb120Cri(aCampos,@cArq)
+----------------------------------------------------------------+
| Carrega dados para MSGETDB |
+----------------------------------------------------------------+
Ctb120Carr(nOpc)
If nOpc == 3 // Inclusao
cRateio := CriaVar("CTJ_RATEIO") // Numero do Rateio
cDescRat := CriaVar("CTJ_DESC") // Descricao do Rateio
cMoedaLC := CriaVar("CTJ_MOEDLC") // Moeda do Lancamento
cTpSald := CriaVar("CTJ_TPSALD") // Tipo do Saldo
Else // Visualizacao / Alteracao / Exclusao
cRateio := CTJ->CTJ_RATEIO
cDescRat := CTJ->CTJ_DESC
cMoedaLC := CTJ->CTJ_MOEDLC
cTpSald := CTJ->CTJ_TPSALD
EndIf
+----------------------------------------------------------------+
| Monta Tela Modelo 2 |
+----------------------------------------------------------------+
DEFINE MSDIALOG oDlg TITLE OemToAnsi(STR0006) From 9,0 To 32,80 OF oMainWnd //"Rateios
Externos"
DEFINE FONT oFnt NAME "Arial" Size 10,15
@ 18, 007 SAY OemToAnsi(STR0007) PIXEL //"Rateio: "
@ 18, 037 MSGET cRateio Picture "9999" SIZE 020,08 When (nOpc == 3);
Valid Ctb120Rat(cRateio) OF oDlg PIXEL
107
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |CTB120GRA| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Grava resgistro digitados |
+------------+-----------------------------------------------------------+
| Sintaxe | Ctb120Gra(ExpC1,ExpC2,ExpN1,cExpC3,cExpC4) |
+------------+-----------------------------------------------------------+
| Parametros | ExpC1 = Numero do Rateio |
| | ExpC2 = Descricao do Rateio |
| | ExpN1 = Opcao do Menu (Inclusao / Alteracao etc) |
| | ExpC3 = Moeda do Rateio |
| | ExpC4 = Tipo de Saldo |
+------------+-----------------------------------------------------------+
| Retorno | Nenhum |
+------------+-----------------------------------------------------------+
| Uso | CTBA120 |
+------------+-----------------------------------------------------------+
Function Ctb120Gra(cRateio,cDescRat,nOpc,cMoedaLC,cTpSald)
Local aSaveArea := GetArea()
dbSelectArea("TMP")
dbgotop()
While !Eof()
If !TMP->CTJ_FLAG // Item nao deletado na MSGETDB
If nOpc == 3 .Or. nOpc == 4
dbSelectArea("CTJ")
dbSetOrder(1)
If !(dbSeek(xFilial()+cRateio+TMP->CTJ_SEQUEN))
RecLock( "CTJ", .t. )
CTJ->CTJ_FILIAL := xFilial()
CTJ->CTJ_RATEIO := cRateio
CTJ->CTJ_DESC := cDescRat
CTJ->CTJ_MOEDLC := cMoedaLC
CTJ->CTJ_TPSALD := cTpSald
Else
RecLock( "CTJ", .f. )
CTJ->CTJ_DESC := cDescRat
CTJ->CTJ_MOEDLC := cMoedaLC
CTJ->CTJ_TPSALD := cTpSald
Endif
For nCont := 1 To Len(aHeader)
108
If (aHeader[nCont][10] != "V" )
FieldPut(FieldPos(aHeader[nCont][2]),;
TMP->(FieldGet(FieldPos(aHeader[nCont][2]))))
EndIf
Next nCont
MsUnLock()
Elseif nOpc == 5 // Se for exclusao
dbSelectArea("CTJ")
dbSetOrder(1)
If dbSeek(xFilial()+cRateio+TMP->CTJ_SEQUEN)
RecLock("CTJ",.F.,.T.)
dbDelete()
MsUnlOCK()
EndIf
EndIf
Else // Item deletado na MSGETDB
dbSelectArea("CTJ")
dbSetOrder(1)
If dbSeek(xFilial()+cRateio+TMP->CTJ_SEQUEN)
RecLock( "CTJ", .f., .t. )
DbDelete()
MsUnlock()
Endif
EndIf
dbSelectArea("TMP")
dbSkip()
Enddo
RestArea(aSaveArea)
Return
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |CTB120TOK| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Valida MSGETDB -> Tudo OK |
+------------+-----------------------------------------------------------+
| Sintaxe | Ctb120TOK(ExpC1) |
+------------+-----------------------------------------------------------+
| Parametros | Nenhum |
+------------+-----------------------------------------------------------+
| Retorno | Nenhum |
+------------+-----------------------------------------------------------+
| Uso | CTBA120 |
+------------+-----------------------------------------------------------+
/*/
Function Ctb120TOk()
Local aSaveArea := GetArea()
Local lRet := .T.
Local nTotalD := 0
Local nTotalC := 0
dbSelectArea("TMP")
dbGotop()
While !Eof()
If !TMP->CTJ_FLAG
If !Ctb120LOK()
lRet := .F.
Exit
EndiF
If !Empty(TMP->CTJ_DEBITO)
nTotalD += TMP->CTJ_PERCEN
EndIf
If !Empty(TMP->CTJ_CREDITO)
nTotalC += TMP->CTJ_PERCEN
EndIf
EndIf
dbSkip()
EndDo
nTotalD := Round(nTotalD,2)
nTotalC := Round(nTotalC,2)
If lRet
IF (nTotalD > 0 .And. nTotalD != 100 ).Or. (nTotalC > 0 .And. nTotalC != 100)
109
Help(" ",1,"CTJ100%")
lRet := .F.
EndIF
EndIf
RestArea(aSaveArea)
Return lRet
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |CTB120LOK| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Valida MSGETDB -> LinhaOK |
+------------+-----------------------------------------------------------+
| Sintaxe | Ctb120LOK(ExpC1) |
+------------+-----------------------------------------------------------+
| Parametros | Nenhum |
+------------+-----------------------------------------------------------+
| Retorno | Nenhum |
+------------+-----------------------------------------------------------+
| Uso | CTBA120 |
+------------+-----------------------------------------------------------+
/*/
Function CTB120LOK()
Local lRet := .T.
Local nCont
If !TMP->CTJ_FLAG
If Empty(TMP->CTJ_PERCEN)
Help(" ",1,"CTJVLZERO")
lRet := .F.
EndIf
If lRet
ValidaConta(TMP->CTJ_DEBITO,"1",,,.t.)
EndIf
If lRet
ValidaConta(TMP->CTJ_CREDITO,"2",,,.T.)
EndIf
EndIf
Return lRet
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |CTB120Cri| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Cria Arquivo Temporario para MSGETDB |
+------------+-----------------------------------------------------------+
| Sintaxe | Ctb120Cri(ExpA1,ExpC1) |
+------------+-----------------------------------------------------------+
| Parametros | ExpA1 = Matriz com campos a serem criados |
| | ExpC1 = Nome do arquivo temporario |
+------------+-----------------------------------------------------------+
| Retorno | Nenhum |
+------------+-----------------------------------------------------------+
| Uso | CTBA120 |
+------------+-----------------------------------------------------------+
/*/
Function Ctb120Cria(aCampos,cArq)
Local cChave
Local aSaveArea := GetArea()
cChave := "CTJ_SEQUEN"
cArq := CriaTrab(aCampos,.t.)
dbUseArea(.t.,,cArq,"TMP",.f.,.f.)
RestArea(aSaveArea)
Return
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |CTB120Head| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+----------+-------+-----------------------+------+----------+
| Descricao | Montar aHeader para arquivo temporario da MSGETDB |
+------------+------------------------------------------------------------+
| Sintaxe | Ctb120Head(ExpA1) |
+------------+------------------------------------------------------------+
| Parametros | ExpA1 = Matriz com campos que podem ser alterados |
+------------+------------------------------------------------------------+
110
111
dbSelectArea("CTJ")
dbSkip()
EndDo
EndIf
Else
dbSelectArea("TMP")
dbAppend()
For nCont := 1 To Len(aHeader)
If (aHeader[nCont][08] <> "M" .And. aHeader[nCont][10] <> "V" )
nPos := FieldPos(aHeader[nCont][2])
FieldPut(nPos,CriaVar(aHeader[nCont][2],.T.))
EndIf
Next nCont
TMP->CTJ_FLAG := .F.
TMP->CTJ_SEQUEN:= "001"
EndIf
dbSelectArea("TMP")
dbGoTop()
RestArea(aSaveArea)
Return
/*/
+------------+---------+-------+-----------------------+------+----------+
| Funcao |CT120Moed| Autor | Pilar S. Albaladejo | Data | 24/07/00 |
+------------+---------+-------+-----------------------+------+----------+
| Descricao | Valida Moeda do Lancamento |
+------------+-----------------------------------------------------------+
| Sintaxe | Ctb120Moed(ExpC1) |
+------------+-----------------------------------------------------------+
| Parametros | ExpC1 = Moeda a ser validada |
+------------+-----------------------------------------------------------+
| Retorno | .T./.F. |
+------------+-----------------------------------------------------------+
| Uso | CTBA120 |
+------------+-----------------------------------------------------------+
/*/
Function Ct120MoedLC(cMoeda)
Local aCtbMoeda:= {}
Local lRet := .T.
aCtbMoeda := CtbMoeda(cMoeda)
If Empty(aCtbMoeda[1])
Help(" ",1,"NOMOEDA")
lRet := .F.
Endif
Return lRet
Modelo 3
Este modelo de programa é a junção dos Modelos 1 e 2. Nele é exibido um Browse vertical e um Browse
horizontal (ambos dependentes do dicionário de dados). As validações são genericamente herdadas do
dicionário de dados.
112
/*/
+---------------------------------------------------------------------------+
+ Funcao | FATA010 | Autor | Eduardo Riera | Data | 11/01/00 |
+-----------+----------+-------+-----------------------+------+-------------+
| Descricao | Cadastro de Processo de Vendas |
+-----------+---------------------------------------------------------------+
| Sintaxe | FATA010() |
+-----------+---------------------------------------------------------------+
| Uso | Generico |
+---------------------------------------------------------------------------+
| ATUALIZACOES SOFRIDAS DESDE A CONSTRUCAO NICIAL |
+-----------+--------+------+-----------------------------------------------+
|Programador| Data | BOPS | Motivo da Alteracao |
+-----------+--------+------+-----------------------------------------------+
| | | | |
+-----------+--------+------+-----------------------------------------------+
/*/
#INCLUDE "FATA010.CH"
#INCLUDE "FIVEWIN.CH"
#DEFINE APOS { 15, 1, 70, 315 }
Function Fata010()
/*/
+----------------------------------------------------------------+
| Define Array contendo as Rotinas a executar do programa +
| ----------- Elementos contidos por dimensao ------------ +
| 1. Nome a aparecer no cabecalho +
| 2. Nome da Rotina associada +
| 3. Usado pela rotina +
113
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Ft010Visua| Autor |Eduardo Riera | Data |13.01.2000|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de Tratamento da Visualizacao |
+------------+------------------------------------------------------------+
| Sintaxe | Ft010Visua(ExpC1,ExpN2,ExpN3) |
+------------+------------------------------------------------------------+
| Parametros | ExpC1: Alias do arquivo |
| | ExpN2: Registro do Arquivo |
| | ExpN3: Opcao da MBrowse |
+------------+------------------------------------------------------------+
| Retorno | Nenhum |
+------------+------------------------------------------------------------+
| Uso | FATA010 |
+------------+------------------------------------------------------------+
/*/
Function Ft010Visua(cAlias,nReg,nOpcx)
Local aArea := GetArea()
Local oGetDad
Local oDlg
Local nUsado := 0
Local nCntFor := 0
Local nOpcA := 0
Local lContinua := .T.
Local lQuery := .F.
Local cCadastro := OemToAnsi(STR0001) //"Processo de Venda"
Local cQuery := ""
Local cTrab := "AC2"
Local bWhile := {|| .T. }
Local aObjects := {}
Local aPosObj := {}
Local aSizeAut := MsAdvSize()
PRIVATE aHEADER := {}
PRIVATE aCOLS := {}
PRIVATE aGETS := {}
PRIVATE aTELA := {}
+----------------------------------------------------------------+
| Montagem de Variaveis de Memoria |
+----------------------------------------------------------------+
dbSelectArea("AC1")
dbSetOrder(1)
For nCntFor := 1 To FCount()
M->&(FieldName(nCntFor)) := FieldGet(nCntFor)
Next nCntFor
+----------------------------------------------------------------+
| Montagem do aHeader |
+----------------------------------------------------------------+
dbSelectArea("SX3")
dbSetOrder(1)
114
dbSeek("AC2")
While ( !Eof() .And. SX3->X3_ARQUIVO == "AC2" )
If ( X3USO(SX3->X3_USADO) .And. cNivel >= SX3->X3_NIVEL )
nUsado++
Aadd(aHeader,{ TRIM(X3Titulo()),;
TRIM(SX3->X3_CAMPO),;
SX3->X3_PICTURE,;
SX3->X3_TAMANHO,;
SX3->X3_DECIMAL,;
SX3->X3_VALID,;
SX3->X3_USADO,;
SX3->X3_TIPO,;
SX3->X3_ARQUIVO,;
SX3->X3_CONTEXT } )
EndIf
dbSelectArea("SX3")
dbSkip()
EndDo
+----------------------------------------------------------------+
| Montagem do aCols |
+----------------------------------------------------------------+
dbSelectArea("AC2")
dbSetOrder(1)
#IFDEF TOP
If ( TcSrvType()!="AS/400" )
lQuery := .T.
cQuery := "SELECT *,R_E_C_N_O_ AC2RECNO "
cQuery += "FROM "+RetSqlName("AC2")+" AC2 "
cQuery += "WHERE AC2.AC2_FILIAL='"+xFilial("AC2")+"' AND "
cQuery += "AC2.AC2_PROVEN='"+AC1->AC1_PROVEN+"' AND "
cQuery += "AC2.D_E_L_E_T_<>'*' "
cQuery += "ORDER BY "+SqlOrder(AC2->(IndexKey()))
cQuery := ChangeQuery(cQuery)
cTrab := "FT010VIS"
dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cTrab,.T.,.T.)
For nCntFor := 1 To Len(aHeader)
TcSetField(cTrab,AllTrim(aHeader[nCntFor][2]),aHeader[nCntFor,8],aHeader[nCnt
For,4],aHeader[nCntFor,5])
Next nCntFor
Else
#ENDIF
AC2->(dbSeek(xFilial("AC2")+AC1->AC1_PROVEN))
bWhile := {|| xFilial("AC2") == AC2->AC2_FILIAL .And.;
AC1->AC1_PROVEN == AC2->AC2_PROVEN }
#IFDEF TOP
EndIf
#ENDIF
115
116
EndIf
dbSelectArea("SX3")
dbSkip()
EndDo
+----------------------------------------------------------------+
| Montagem da Acols |
+----------------------------------------------------------------+
aadd(aCOLS,Array(nUsado+1))
For nCntFor := 1 To nUsado
aCols[1][nCntFor] := CriaVar(aHeader[nCntFor][2])
Next nCntFor
aCOLS[1][Len(aHeader)+1] := .F.
aObjects := {}
AAdd( aObjects, { 315, 50, .T., .T. } )
AAdd( aObjects, { 100, 100, .T., .T. } )
aInfo := { aSizeAut[ 1 ], aSizeAut[ 2 ], aSizeAut[ 3 ], aSizeAut[ 4 ], 3, 3 }
aPosObj := MsObjSize( aInfo, aObjects, .T. )
DEFINE MSDIALOG oDlg TITLE cCadastro From aSizeAut[7],00 To aSizeAut[6],aSizeAut[5] OF
oMainWnd PIXEL
EnChoice( cAlias ,nReg, nOpcx, , , , , aPosObj[1], , 3 )
oGetDad := MSGetDados():New(aPosObj[2,1], aPosObj[2,2], aPosObj[2,3], aPosObj[2,4],
nOpcx, "Ft010LinOk", "Ft010TudOk","",.T.)
ACTIVATE MSDIALOG oDlg ;
ON INIT EnchoiceBar(oDlg, {||nOpcA:=If(oGetDad:TudoOk() .And. Obrigatorio(aGets,aTela),
1,0),If(nOpcA==1,oDlg:End(),Nil)},{||oDlg:End()})
If ( nOpcA == 1 )
Begin Transaction
Ft010Grv(1)
If ( __lSX8 )
ConfirmSX8()
EndIf
EvalTrigger()
End Transaction
Else
If ( __lSX8 )
RollBackSX8()
EndIf
EndIf
RestArea(aArea)
Return(.T.)
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Ft010Alter| Autor |Eduardo Riera | Data |13.01.2000|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de Tratamento da Alteracao |
+------------+------------------------------------------------------------+
| Sintaxe | Ft010Alter(ExpC1,ExpN2,ExpN3) |
+------------+------------------------------------------------------------+
| Parametros | ExpC1: Alias do arquivo |
| | ExpN2: Registro do Arquivo |
| | ExpN3: Opcao da MBrowse |
+------------+------------------------------------------------------------+
| Retorno | Nenhum |
+------------+------------------------------------------------------------+
| Uso | FATA010 |
+------------+------------------------------------------------------------+
/*/
Function Ft010Alter(cAlias,nReg,nOpcx)
Local aArea := GetArea()
Local cCadastro := OemToAnsi(STR0001) //"Processo de Venda"
Local oGetDad
Local oDlg
Local nUsado := 0
Local nCntFor := 0
Local nOpcA := 0
Local lContinua := .T.
Local cQuery := ""
Local cTrab := "AC2"
Local bWhile := {|| .T. }
Local aObjects := {}
Local aPosObj := {}
117
cQuery := ChangeQuery(cQuery)
cTrab := "FT010VIS"
dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cTrab,.T.,.T.)
For nCntFor := 1 To Len(aHeader)
TcSetField(cTrab,AllTrim(aHeader[nCntFor][2]),aHeader[nCntFor,8],;
Header[nCntFor,4],aHeader[nCntFor,5])
Next nCntFor
Else
#ENDIF
AC2->(dbSeek(xFilial("AC2")+AC1->AC1_PROVEN))
bWhile := {|| xFilial("AC2") == AC2->AC2_FILIAL .And.;
AC1->AC1_PROVEN == AC2->AC2_PROVEN }
#IFDEF TOP
EndIf
#ENDIF
While ( !Eof() .And. Eval(bWhile) )
aadd(aCOLS,Array(nUsado+1))
For nCntFor := 1 To nUsado
118
If ( aHeader[nCntFor][10] != "V" )
aCols[Len(aCols)][nCntFor] :=
FieldGet(FieldPos(aHeader[nCntFor][2]))
Else
If ( lQuery )
AC2->(dbGoto((cTrab)->AC2RECNO))
EndIf
aCols[Len(aCols)][nCntFor] := CriaVar(aHeader[nCntFor][2])
EndIf
Next nCntFor
aCOLS[Len(aCols)][Len(aHeader)+1] := .F.
dbSelectArea(cTrab)
dbSkip()
EndDo
If ( lQuery )
dbSelectArea(cTrab)
dbCloseArea()
dbSelectArea(cAlias)
EndIf
EndIf
If ( lContinua )
aObjects := {}
AAdd( aObjects, { 315, 50, .T., .T. } )
AAdd( aObjects, { 100, 100, .T., .T. } )
aInfo := { aSizeAut[ 1 ], aSizeAut[ 2 ], aSizeAut[ 3 ], aSizeAut[ 4 ], 3, 3 }
aPosObj := MsObjSize( aInfo, aObjects, .T. )
DEFINE MSDIALOG oDlg TITLE cCadastro From aSizeAut[7],00 To aSizeAut[6],aSizeAut[5]
;
OF MainWnd PIXEL
EnChoice( cAlias ,nReg, nOpcx, , , , , aPosObj[1], , 3 )
oGetDad :=
MSGetDados():New(aPosObj[2,1],aPosObj[2,2],aPosObj[2,3],aPosObj[2,4],nOpcx,;
"Ft010LinOk","Ft010TudOk","",.T.)
ACTIVATE MSDIALOG oDlg ;
ON INIT
EnchoiceBar(oDlg,{||nOpca:=If(oGetDad:TudoOk().And.Obrigatorio(aGets,aTela),1,0),;
If(nOpcA==1,oDlg:End(),Nil)},{||oDlg:End()})
If ( nOpcA == 1 )
Begin Transaction
Ft010Grv(2)
If ( __lSX8 )
ConfirmSX8()
EndIf
EvalTrigger()
End Transaction
Else
If ( __lSX8 )
RollBackSX8()
EndIf
EndIf
EndIf
Endif
RestArea(aArea)
Return(.T.)
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Ft010Exclu| Autor |Eduardo Riera | Data |13.01.2000|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de Tratamento da Exclusao |
+------------+------------------------------------------------------------+
| Sintaxe | Ft010Exclu(ExpC1,ExpN2,ExpN3) |
+------------+------------------------------------------------------------+
| Parametros | ExpC1: Alias do arquivo |
| | ExpN2: Registro do Arquivo |
| | ExpN3: Opcao da MBrowse |
+------------+------------------------------------------------------------+
| Retorno | Nenhum |
+------------+------------------------------------------------------------+
| Uso | FATA010 |
+------------+------------------------------------------------------------+
/*/
119
Function Ft010Exclu(cAlias,nReg,nOpcx)
Local aArea := GetArea()
Local cCadastro := OemToAnsi(STR0001) //"Processo de Venda"
Local oGetDad
Local oDlg
Local nUsado := 0
Local nCntFor := 0
Local nOpcA := 0
Local lContinua := .T.
Local cQuery := ""
Local cTrab := "AC2"
Local bWhile := {|| .T. }
Local aObjects := {}
Local aPosObj := {}
Local aSizeAut := MsAdvSize()
PRIVATE aHEADER := {}
PRIVATE aCOLS := {}
PRIVATE aGETS := {}
PRIVATE aTELA := {}
+----------------------------------------------------------------+
| Montagem das Variaveis de Memoria |
+----------------------------------------------------------------+
dbSelectArea("AC1")
dbSetOrder(1)
lContinua := SoftLock("AC1")
If ( lContinua )
For nCntFor := 1 To FCount()
M->&(FieldName(nCntFor)) := FieldGet(nCntFor)
Next nCntFor
+----------------------------------------------------------------+
| Montagem da aHeader |
+----------------------------------------------------------------+
dbSelectArea("SX3")
dbSetOrder(1)
dbSeek("AC2")
While ( !Eof() .And. SX3->X3_ARQUIVO == "AC2" )
If ( X3USO(SX3->X3_USADO) .And. cNivel >= SX3->X3_NIVEL )
nUsado++
Aadd(aHeader,{ TRIM(X3Titulo()),;
TRIM(SX3->X3_CAMPO),;
SX3->X3_PICTURE,;
SX3->X3_TAMANHO,;
SX3->X3_DECIMAL,;
SX3->X3_VALID,;
SX3->X3_USADO,;
SX3->X3_TIPO,;
SX3->X3_ARQUIVO,;
SX3->X3_CONTEXT } )
EndIf
dbSelectArea("SX3")
dbSkip()
EndDo
+----------------------------------------------------------------+
| Montagek da aCols |
+----------------------------------------------------------------+
dbSelectArea("AC2")
dbSetOrder(1)
#IFDEF TOP
If ( TcSrvType()!="AS/400" )
lQuery := .T.
cQuery := "SELECT *,R_E_C_N_O_ AC2RECNO "
cQuery += "FROM "+RetSqlName("AC2")+" AC2 "
cQuery += "WHERE AC2.AC2_FILIAL='"+xFilial("AC2")+"' AND "
cQuery += "AC2.AC2_PROVEN='"+AC1->AC1_PROVEN+"' AND "
cQuery += "AC2.D_E_L_E_T_<>'*' "
cQuery += "ORDER BY "+SqlOrder(AC2->(IndexKey()))
cQuery := ChangeQuery(cQuery)
cTrab := "FT010VIS"
dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cTrab,.T.,.T.)
For nCntFor := 1 To Len(aHeader)
120
TcSetField(cTrab,AllTrim(aHeader[nCntFor][2]),aHeader[nCntFor,8],;
aHeader[nCntFor,4],aHeader[nCntFor,5])
Next nCntFor
Else
#ENDIF
AC2->(dbSeek(xFilial("AC2")+AC1->AC1_PROVEN))
bWhile := {|| xFilial("AC2") == AC2->AC2_FILIAL .And.;
AC1->AC1_PROVEN == AC2->AC2_PROVEN }
#IFDEF TOP
EndIf
#ENDIF
While ( !Eof() .And. Eval(bWhile) )
aadd(aCOLS,Array(nUsado+1))
For nCntFor := 1 To nUsado
If ( aHeader[nCntFor][10] != "V" )
aCols[Len(aCols)][nCntFor] :=
FieldGet(FieldPos(aHeader[nCntFor][2]))
Else
If ( lQuery )
AC2->(dbGoto((cTrab)->AC2RECNO))
EndIf
aCols[Len(aCols)][nCntFor] := CriaVar(aHeader[nCntFor][2])
EndIf
Next nCntFor
aCOLS[Len(aCols)][Len(aHeader)+1] := .F.
dbSelectArea(cTrab)
dbSkip()
EndDo
If ( lQuery )
dbSelectArea(cTrab)
dbCloseArea()
dbSelectArea(cAlias)
EndIf
EndIf
If ( lContinua )
aObjects := {}
AAdd( aObjects, { 315, 50, .T., .T. } )
AAdd( aObjects, { 100, 100, .T., .T. } )
aInfo := { aSizeAut[ 1 ], aSizeAut[ 2 ], aSizeAut[ 3 ], aSizeAut[ 4 ], 3, 3 }
aPosObj := MsObjSize( aInfo, aObjects, .T. )
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Ft010LinOK| Autor |Eduardo Riera | Data |13.01.2000|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de Validacao da linha OK |
+------------+------------------------------------------------------------+
| Sintaxe | Ft010LinOk() |
121
+------------+------------------------------------------------------------+
| Parametros | Nennhum |
+------------+------------------------------------------------------------+
| Retorno | Nenhum |
+------------+------------------------------------------------------------+
| Uso | FATA010 |
+------------+------------------------------------------------------------+
/*/
Function Ft010LinOk()
Local lRetorno:= .T.
Local nPStage := aScan(aHeader,{|x| AllTrim(x[2])=="AC2_STAGE"})
Local nPDescri:= aScan(aHeader,{|x| AllTrim(x[2])=="AC2_DESCRI"})
Local nCntFor := 0
Local nUsado := Len(aHeader)
If ( !aCols[n][nUsado+1] )
+----------------------------------------------------------------+
| Verifica os campos obrigatorios |
+----------------------------------------------------------------+
If ( nPStage == 0 .Or. nPDescri == 0 )
Help(" ",1,"OBRIGAT")
lRetorno := .F.
EndIf
If ( lRetorno .And. (Empty(aCols[n][nPStage]) .Or. Empty(aCols[n][nPDescri])))
Help(" ",1,"OBRIGAT")
lRetorno := .F.
EndIf
+----------------------------------------------------------------+
| Verifica se não há estagios repetidos |
+----------------------------------------------------------------+
If ( nPStage != 0 .And. lRetorno )
For nCntFor := 1 To Len(aCols)
If ( nCntFor != n .And. !aCols[nCntFor][nUsado+1])
If ( aCols[n][nPStage] == aCols[nCntFor][nPStage] )
Help(" ",1,"FT010LOK01")
lRetorno := .F.
EndIf
EndIf
Next nCntFor
EndIf
EndIf
Return(lRetorno)
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Ft010Grv | Autor |Eduardo Riera | Data |13.01.2000|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de Gravacao do Processe de Venda |
+------------+------------------------------------------------------------+
| Sintaxe | Ft010Grv(ExpN1) |
+------------+------------------------------------------------------------+
| Parametros | ExpN1: Opcao do Menu (Inclusao / Alteracao / Exclusao) |
+------------+------------------------------------------------------------+
| Retorno | .T. |
+------------+------------------------------------------------------------+
| Uso | FATA010 |
+------------+------------------------------------------------------------+
/*/
Static Function Ft010Grv(nOpc)
Local aArea := GetArea()
Local aUsrMemo := If( ExistBlock( "FT010MEM" ), ExecBlock( "FT010MEM", .F.,.F. ), {} )
Local aMemoAC1 := {}
Local aMemoAC2 := {}
Local aRegistro := {}
Local cQuery := ""
Local lGravou := .F.
Local nCntFor := 0
Local nCntFor2 := 0
Local nUsado := Len(aHeader)
Local nPStage := aScan(aHeader,{|x| AllTrim(x[2])=="AC2_STAGE"})
Local nPMEMO := aScan(aHeader,{|x| AllTrim(x[2])=="AC2_MEMO"})
122
EndIf
Next nLoop
EndIf
+----------------------------------------------------------------+
| Guarda os registros em um array para atualizacao |
+----------------------------------------------------------------+
dbSelectArea("AC2")
dbSetOrder(1)
#IFDEF TOP
If ( TcSrvType()!="AS/400" )
cQuery := "SELECT AC2.R_E_C_N_O_ AC2RECNO "
cQuery += "FROM "+RetSqlName("AC2")+" AC2 "
cQuery += "WHERE AC2.AC2_FILIAL='"+xFilial("AC2")+"' AND "
cQuery += "AC2.AC2_PROVEN='"+M->AC1_PROVEN+"' AND "
cQuery += "AC2.D_E_L_E_T_<>'*' "
cQuery += "ORDER BY "+SqlOrder(AC2->(IndexKey()))
cQuery := ChangeQuery(cQuery)
dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),"FT010GRV",.T.,.T.)
dbSelectArea("FT010GRV")
While ( !Eof() )
aadd(aRegistro,AC2RECNO)
dbSelectArea("FT010GRV")
dbSkip()
EndDo
dbSelectArea("FT010GRV")
dbCloseArea()
dbSelectArea("AC2")
Else
#ENDIF
dbSeek(xFilial("AC2")+M->AC1_PROVEN)
While ( !Eof() .And. xFilial("AC2") == AC2->AC2_FILIAL .And.;
M->AC1_PROVEN == AC2->AC2_PROVEN )
aadd(aRegistro,AC2->(RecNo()))
dbSelectArea("AC2")
dbSkip()
EndDo
#IFDEF TOP
EndIf
#ENDIF
Do Case
+----------------------------------------------------------------+
| Inclusao / Alteracao |
+----------------------------------------------------------------+
Case nOpc != 3
For nCntFor := 1 To Len(aCols)
If ( nCntFor > Len(aRegistro) )
If ( !aCols[nCntFor][nUsado+1] )
RecLock("AC2",.T.)
EndIf
Else
AC2->(dbGoto(aRegistro[nCntFor]))
RecLock("AC2")
EndIf
If ( !aCols[nCntFor][nUsado+1] )
lGravou := .T.
For nCntFor2 := 1 To nUsado
If ( aHeader[nCntFor2][10] != "V" )
FieldPut(FieldPos(aHeader[nCntFor2][2]),aCols[nCntFor][nCn
tFor2])
EndIf
Next nCntFor2
+----------------------------------------------------------------+
| Grava os campos obrigatorios |
123
+----------------------------------------------------------------+
AC2->AC2_FILIAL := xFilial("AC2")
AC2->AC2_PROVEN := M->AC1_PROVEN
If ( nPMemo != 0 .And. !Empty(aCols[nCntFor][nPMemo]))
MSMM(AC2-
>AC2_CODMEM,,,aCols[nCntFor][nPMemo],1,,,"AC2","AC2_CODMEM")
EndIf
+----------------------------------------------------------------+
| Grava os campos memo de usuario |
+----------------------------------------------------------------+
For nLoop := 1 To Len( aMemoAC2 )
MSMM(AC2->(FieldGet(aMemoAC2[nLoop,1])),,, ;
DFieldGet( aMemoAC2[nLoop,2], nCntFor
),1,,,"AC2",aMemoAC2[nLoop,1])
Next nLoop
Else
If ( nCntFor <= Len(aRegistro) )
dbDelete()
MSMM(AC2->AC2_CODMEM,,,,2)
+----------------------------------------------------------------
+
| Exclui os campos memo de usuario
|
+----------------------------------------------------------------
+
For nLoop := 1 To Len( aMemoAC2 )
MSMM(aMemoAC2[nLoop,1],,,,2)
Next nLoop
EndIf
EndIf
MsUnLock()
Next nCntFor
+----------------------------------------------------------------+
| Exclusao |
+----------------------------------------------------------------+
OtherWise
For nCntFor := 1 To Len(aRegistro)
AC2->(dbGoto(aRegistro[nCntFor]))
RecLock("AC2")
dbDelete()
MsUnLock()
MSMM(AC2->AC2_CODMEM,,,,2)
Next nCntFor
EndCase
+----------------------------------------------------------------+
| Atualizacao do cabecalho |
+----------------------------------------------------------------+
dbSelectArea("AC1")
dbSetOrder(1)
If ( MsSeek(xFilial("AC1")+M->AC1_PROVEN) )
RecLock("AC1")
Else
If ( lGravou )
RecLock("AC1",.T.)
EndIf
EndIf
If ( !lGravou )
dbDelete()
MSMM(AC1->AC1_CODMEM,,,,2)
+----------------------------------------------------------------+
124
AD1->( dbSetOrder( 5 ) )
If AD1->( dbSeek( xFilial( "AD1" ) + M->AC1_PROVEN +
aCols[nLoop,nPosStage] ) )
Aviso( STR0007, STR0011 + AllTrim( aCols[nLoop,nPosStage] ) + ;
STR0012, { STR0009 }, 2 ) ;
// Atencao // "A etapa " // " nao pode ser excluida pois esta em
uso por uma ou mais // oportunidades !"
lRet := .F.
Exit
EndIf
125
EndIf
Next nLoop
If lRet
If nTotal <> 100
Aviso( STR0007, STR0008, ;
{ STR0009 }, 2 ) //"Atencao !"###"A soma dos valores de relevancia
deve ser igual a 100% //!"###"Fechar"
lRet := .F.
EndIf
EndIf
EndIf
Return( lRet )
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Ft010DelOk| Autor |Sergio Silveira | Data |18.01.2001|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Validacao da Exclusao |
+------------+------------------------------------------------------------+
| Sintaxe | Ft010DelOk() |
+------------+------------------------------------------------------------+
| Parametros | Nenhum |
+------------+------------------------------------------------------------+
| Retorno | .T./.F. |
+------------+------------------------------------------------------------+
| Uso | FATA010 |
+------------+------------------------------------------------------------+
/*/
Static Function Ft010DelOk()
LOCAL lRet := .T.
AD1->( dbSetOrder( 5 ) )
If AD1->( dbSeek( xFilial( "AD1" ) + M->AC1_PROVEN ) )
lRet := .F.
Aviso( STR0007, STR0010, { STR0009 }, 2 ) // "Atencao"
// "Este processo de venda nao pode ser excluido pois esta sendo utilizado em uma
ou mais
// oportunidades !", "Fechar"
EndIf
Return( lRet )
/*/
+---------------------------------------------------------------------------+
+ Funcao | MATR425 | Autor | Rodrigo de Sartorio | Data | 11/05/95 |
+-----------+----------+-------+-----------------------+------+-------------+
| Descricao | Relatorio de Estoque por Lote |
+-----------+---------------------------------------------------------------+
| Sintaxe | MATR425() |
+-----------+---------------------------------------------------------------+
| Uso | Generico |
+---------------------------------------------------------------------------+
| ATUALIZACOES SOFRIDAS DESDE A CONSTRUCAO NICIAL |
+-----------+--------+------+-----------------------------------------------+
|Programador| Data | BOPS | Motivo da Alteracao |
+-----------+--------+------+-----------------------------------------------+
| | | | |
+-----------+--------+------+-----------------------------------------------+
/*/
#include 'MATR425.CH'
126
#include 'FIVEWIN.CH'
Function MATR425()
+----------------------------------------------------------------+
| Define Variaveis |
+----------------------------------------------------------------+
Local cDesc1 := STR0001 //"Este programa emitira' uma relacao com a posi‡„o de "
Local cDesc2 := STR0002 //"estoque por Lote/Sub-Lote."
Local cDesc3 := ''
Local cString := 'SB8'
Local Titulo := STR0003 //"Posicao de Estoque por Lote/Sub-Lote"
Local Tamanho := 'M'
Local wnRel := 'MATR425'
+----------------------------------------------------------------+
| Variaveis Tipo Private padrao de todos os relatorios |
+----------------------------------------------------------------+
Private aOrd := {STR0004,STR0005} //" Por Produto"###" Por Lote/Sub-Lote"
Private aReturn := {STR0006,1,STR0007, 1, 2, 1, '',1 } //"Zebrado"###"Administracao"
Private cPerg := 'MR425A'
Private nLastKey := 0
Private nTipo := 0
+----------------------------------------------------------------+
| Verifica as perguntas selecionadas |
+----------------------------------------------------------------+
Pergunte('MR425A', .F.)
+----------------------------------------------------------------+
| Variaveis utilizadas para parametros |
| mv_par01 // Do Produto |
| mv_par02 // Ate Produto |
| mv_par03 // De Lote |
| mv_par04 // Ate Lote |
| mv_par05 // De Sub-Lote |
| mv_par06 // Ate Sub-Lote |
| mv_par07 // De Local |
| mv_par08 // Ate Local |
| mv_par09 // Lista Saldo Zerado ? Lista/Nao Lista |
| mv_par10 // Do Tipo |
| mv_par11 // Ate o Tipo |
| mv_par12 // Do Grupo |
| mv_par13 // Ate o Grupo |
+----------------------------------------------------------------+
+----------------------------------------------------------------+
| Envia controle para SETPRINT |
+----------------------------------------------------------------+
wnRel := SetPrint(cString,wnRel,cPerg,@Titulo,cDesc1,cDesc2,cDesc3,.F.,aOrd,,Tamanho)
nTipo := If(aReturn[4]==1,GetMv('MV_COMP'),GetMv('MV_NORM'))
If nLastKey == 27
dbClearFilter()
Return Nil
Endif
SetDefault(aReturn,cString)
If nLastKey == 27
dbClearFilter()
Return Nil
Endif
RptStatus({|lEnd| C425Imp(@lEnd,wnRel,Tamanho,Titulo)},Titulo)
Return Nil
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |C425Imp | Autor |Rodrigo Sartorio | Data | 14/11/95 |
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Chamada do Relatorio |
+------------+------------------------------------------------------------+
| Uso | MATR425 |
+------------+------------------------------------------------------------+
/*/
Static Function C425Imp(lEnd, wnRel, Tamanho, Titulo)
+----------------------------------------------------------------+
| Variaveis especificas dos relatorios |
+----------------------------------------------------------------+
Local cIndex := ''
Local cCond := ''
127
VALIDADE "
EndIf
+----------------------------------------------------------------+
| Pega o nome do arquivo de indice de trabalho |
+----------------------------------------------------------------+
cNomArq := CriaTrab('', .F.)
//-- Seta a Ordem Correta no Arquivo SB1
dbSelectArea('SB1')
dbSetOrder(1)
+----------------------------------------------------------------+
| Cria Indice de Trabalho |
+----------------------------------------------------------------+
dbSelectArea('SB8')
IndRegua('SB8', cNomArq, cIndex,, cCond, STR0017) //"Selecionando Registros..."
#IFNDEF TOP
dbSetIndex(cNomArq+OrdBagExt())
#ENDIF
dbGoTop()
SetRegua(LastRec())
+----------------------------------------------------------------+
| Processa o Laco de impressao |
+----------------------------------------------------------------+
128
Do While !Eof()
+----------------------------------------------------------------+
| Cancela a impressao |
+----------------------------------------------------------------+
If lEnd
@ PRow()+1, 001 PSay STR0012 //"CANCELADO PELO OPERADOR"
Exit
EndIf
lSubLote := Rastro(B8_PRODUTO,'S')
//-- Define a Quebra por Produto ou Lote
If aReturn[8] == 1
cSeekSB8 := B8_FILIAL+B8_PRODUTO+B8_LOCAL
cCondSB8 := 'B8_FILIAL+B8_PRODUTO+B8_LOCAL'
Else
cSeekSB8 :=
B8_FILIAL+B8_LOTECTL+If(lSubLote,B8_NUMLOTE,'')+B8_PRODUTO+B8_LOCAL
cCondSB8 :=
'B8_FILIAL+B8_LOTECTL+'+If(lSubLote,'B8_NUMLOTE+','')+'B8_PRODUTO+B8_LOCAL'
EndIf
nSaldo := 0
nEmpenho := 0
nSaldoT := 0
nEmpenhoT := 0
+----------------------------------------------------------------+
| Cancela a Impressao |
+----------------------------------------------------------------+
If lEnd
@ PRow()+1, 001 PSay STR0012 //"CANCELADO PELO OPERADOR"
Exit
EndIf
129
Modelos de Cálculos
130
Existem diversas formas de se gerar uma rotina de cálculo no sistema, no entanto o modelo básico
sempre se mantém. Abaixo mostramos um modelo-padrão que utiliza as funções básicas para tal.
/*/
+---------------------------------------------------------------------------+
+ Funcao | FINA210 | Autor | Wagner Xavier | Data | 01/12/92 |
+-----------+----------+-------+-----------------------+------+-------------+
| Descricao | Recalcula saldos bancarios dentro de um determinado periodo |
+-----------+---------------------------------------------------------------+
| Sintaxe | FINA210() |
+-----------+---------------------------------------------------------------+
| Uso | Generico |
+---------------------------------------------------------------------------+
| ATUALIZACOES SOFRIDAS DESDE A CONSTRUCAO NICIAL |
+-----------+--------+------+-----------------------------------------------+
|Programador| Data | BOPS | Motivo da Alteracao |
+-----------+--------+------+-----------------------------------------------+
| | | | |
+-----------+--------+------+-----------------------------------------------+
#INCLUDE "FINA210.CH"
#INCLUDE "PROTHEUS.CH"
Function FinA210()
LOCAL nOpca :=0
+----------------------------------------------------------------+
| Define Variaveis |
+----------------------------------------------------------------+
LOCAL oDlg, aSays:={}, aButtons:={}
Private cCadastro := OemToAnsi(STR0004) //"Reconciliacao de Saldos Bancarios"
Pergunte("FIN210",.F.)
AADD (aSays,;
OemToAnsi(STR0005))//"Este programa tem como objetivo recalcular e analisar os saldos"
AADD (aSays,;
OemToAnsi(STR0006)) //"Bancarios dia a dia de um determinado periodo ate a data base do
"
AADD (aSays,;
OemToAnsi(STR0007)) //"sistema. Utilizando no caso de haver necessidade de retroagir a
"
AADD (aSays,;
OemToAnsi(STR0008)) //"movimentacao bancaria. Use como referencia a data em que o saldo
"
AADD (aSays,;
OemToAnsi(STR0009)) //"ficou defasado. "
AADD(aButtons, { 1,.T.,{|o| nOpca:= 1,o:oWnd:End()}} )
AADD(aButtons, { 2,.T.,{|o| o:oWnd:End() }} )
AADD(aButtons, { 5,.T.,{|| Pergunte("FIN210",.T. ) } } )
FormBatch( cCadastro, aSays, aButtons )
If nOpcA == 1
#IFDEF TOP
If TcSrvType() == 'AS/400'
Processa({|lEnd| FA210Proc()}) // Chamada da funcao de reconciliacao
Else
Processa({|lEnd| FA211Proc()}) // Chamada da funcao de reconciliacao
Endif
#ELSE
Processa({|lEnd| FA210Proc()}) // Chamada da funcao de reconciliacao
#ENDIF
Endif
Return
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Fa210Proc | Autor |Wagner Xavier | Data |01.12.1992|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de recalculo dos saldos bancarios – CODEBASE |
+------------+------------------------------------------------------------+
| Sintaxe | Fa210Proc () |
+------------+------------------------------------------------------------+
| Parametros | Nenhum |
+------------+------------------------------------------------------------+
| Retorno | Nenhum |
131
+------------+------------------------------------------------------------+
| Uso | FINA210 |
+------------+------------------------------------------------------------+
/*/
Function FA210Processa()
LOCAL nSaldoIni
LOCAL nEntradas
LOCAL nSaidas, nData, cCond
LOCAL dDataMovto
LOCAL cFil :=""
LOCAL lAllFil :=.F.
LOCAL cChave
LOCAL cIndex := ""
LOCAL lSaida :=.F.
+----------------------------------------------------------+
| Variaveis utilizadas para parametros |
| mv_par01 // Do Banco |
| mv_par02 // Ate o Banco |
| mv_par03 // Da Agencia |
| mv_par04 // Ate a Agencia |
| mv_par05 // Da Conta |
| mv_par06 // Ate a Conta |
| mv_par07 // A partir da Data |
+----------------------------------------------------------+
dbSelectArea( "SA6" )
dbSeek( cFilial+mv_par01 , .T.)
ProcRegua(RecCount())
If Empty(xFilial( "SA6")) .AND. !Empty(xFilial("SE5"))
+----------------------------------------------------------------+
| Filtra o arquivo pro tipo e vencimento |
+----------------------------------------------------------------+
dbSelectArea("SE5")
cIndex := CriaTrab(nil,.f.)
cChave := "E5_BANCO+E5_AGENCIA+E5_CONTA+DTOS(E5_DTDISPO)"
cCond := 'dtos(E5_DTDISPO)>="'+dtos(mv_par07)+'"'
IndRegua("SE5",cIndex,cChave,,cCond,OemToAnsi(STR0015)) //"Selecionando
Registros..."
nIndexSE5 := RetIndex("SE5")
#IFNDEF TOP
dbSetIndex(cIndex+OrdBagExt())
#ENDIF
dbSetOrder(nIndexSE5+1)
lSaida := .T.
dbGoTop()
lAllFil:= .T.
Else
dbSelectArea("SE5")
cIndex := CriaTrab(nil,.f.)
cChave := "E5_FILIAL+E5_BANCO+E5_AGENCIA+E5_CONTA+DTOS(E5_DTDISPO)"
cCond := 'dtos(E5_DTDISPO)>="'+dtos(mv_par07)+'" .and. E5_FILIAL ==
"'+xFilial("SE5")+'"'
IndRegua("SE5",cIndex,cChave,,cCond,OemToAnsi(STR0015)) //"Selecionando
Registros..."
nIndexSE5 := RetIndex("SE5")
#IFNDEF TOP
dbSetIndex(cIndex+OrdBagExt())
#ENDIF
dbSetOrder(nIndexSE5+1)
dbGoTop()
Endif
+----------------------------------------------------------------+
| Inicia recalculo dos saldos atraves da movimentacao bancaria |
+----------------------------------------------------------------+
dbSelectArea( "SA6" )
dbSeek( cFilial+mv_par01 , .T.)
While !Eof() .and. A6_FILIAL == cFilial .and. A6_COD <= mv_par02
IncProc()
// Alteracao para nao recalcular o saldo dos caixas do Loja, pois
// estes devem ser recalculados atraves da opcao "Recalculo de Caixa" - Adriano
dbSelectArea("SX5")
If (dbSeek(xFilial("SX5")+"23"+SA6->A6_COD)) .or. (SA6->A6_Cod == "CL1")
132
dbSelectArea("SA6")
dbSkip()
Loop
Endif
dbSelectArea("SA6")
cBanco := A6_COD
cAgencia := A6_AGENCIA
cConta := A6_NUMCON
nSaldoIni:= 0
nEntradas:= 0
nSaidas := 0
If cAgencia < mv_par03 .or. cAgencia > mv_par04 .or. cConta < mv_par05 .or. cConta
> mv_par06
dbSkip( )
Loop
Endif
+---------------------------------------------------------+
| Localiza Saldo de Partida. |
| Observe que o programa retorna um registro no banco de |
| dados, portanto a data de referencia ‚ a data em que |
| o saldo ficou errado, nao a data correta do saldo. |
+---------------------------------------------------------+
dbSelectArea( "SE8" )
dbSeek( cFilial+cBanco+cAgencia+cConta+Dtos(mv_par07),.T. )
dbSkip( -1 )
If E8_BANCO != cBanco .or. E8_AGENCIA != cAgencia .or. E8_CONTA != cConta .or.
BOF() .or. EOF()
nSaldoIni := 0
Else
nSaldoIni := E8_SALATUA
End
+----------------------------------------------------------------+
| Localiza movimentacao bancaria |
+----------------------------------------------------------------+
dbSelectArea( "SE5" )
dbSetOrder(nIndexSE5+1)
cFil := Iif(lAllFil,"",xFilial("SE5"))
dbSeek(cFil+cBanco+cAgencia+cConta+Dtos(mv_par07),.T.)
While !Eof() .and. E5_BANCO+E5_AGENCIA+E5_CONTA == cBanco+cAgencia+cConta
IF !lAllFil .and. E5_FILIAL != xFilial("SE5")
Exit
Endif
dDataMovto := E5_DTDISPO
While !Eof() .and. E5_BANCO+E5_AGENCIA+E5_CONTA+dtos(E5_DTDISPO)== ;
cBanco+cAgencia+cConta+dtos(dDataMovto)
IF !lAllFil .and. E5_FILIAL != xFilial("SE5")
Exit
Endif
IF E5_TIPODOC $ "DC/JR/MT/CM/D2/J2/M2/C2/V2/CP/TL" //Valores de Baixas
dbSkip()
Loop
Endif
If E5_VENCTO > E5_DATA // Ignora pre' datados - gerou titulo
dbSkip()
Loop
Endif
If E5_SITUACA = "C" //Cancelado
dbSkip()
Loop
Endif
If SE5->E5_MOEDA $ "C1/C2/C3/C4/C5" .and. Empty(SE5->E5_NUMCHEQ)
dbSkip()
Loop
Endif
+---------------------------------------------------------------+
| Na transferencia somente considera nestes numerarios |
| No Fina100 ‚ tratado desta forma. |
| As transferencias TR de titulos p/ Desconto/Cau‡Æo (FINA060) |
| nÆo sofrem mesmo tratamento dos TR bancarias do FINA100 |
| Aclaracao : Foi incluido o tipo $ para os movimentos en di-- |
| nheiro em QUALQUER moeda, pois o R$ nao e representativo |
133
| fora do BRASIL. |
+---------------------------------------------------------------+
If SE5->E5_TIPODOC $ "TR/TE" .and. Empty(SE5->E5_NUMERO)
If !(E5_MOEDA $ " $ /R$/DO/TB/TC/CH"+IIf(cPaisLoc=="BRA","","/$
"))
dbSkip()
Loop
Endif
Endif
If E5_TIPODOC $ "TR/TE" .and. (Substr(E5_NUMCHEQ,1,1)=="*" ;
.or. Substr(E5_DOCUMEN,1,1) == "*" )
dbSkip()
Loop
Endif
If SE5->E5_MOEDA == "CH" .and. IsCaixaLoja(SE5->E5_BANCO) //Sangria
dbSkip()
Loop
Endif
If SubStr(E5_NUMCHEQ,1,1)=="*" //cheque para juntar (PA)
dbSkip()
Loop
Endif
If !Empty(SE5->E5_MOTBX)
If !MovBcoBx(SE5->E5_MOTBX)
dbSkip()
Loop
Endif
Endif
+----------------------------------------------------------------+
| Baixa automatica |
+----------------------------------------------------------------+
IF E5_TIPODOC = "BA"
dbSkip()
Loop
Endif
dbSelectArea("SE5")
IF E5_RECPAG = "R"
nEntradas += E5_VALOR
Else
nSaidas += E5_VALOR
Endif
dbSkip()
End // Quebra da data
dbSelectArea("SE8")
dbSeek(cFilial + cBanco+cAgencia+cConta+Dtos(dDataMovto))
IF Eof()
RecLock("SE8",.t.)
Else
RecLock("SE8",.f.)
Endif
Replace E8_FILIAL With cFilial,;
E8_BANCO With cBanco,;
E8_AGENCIA With cAgencia,;
E8_CONTA With cConta,;
E8_DTSALATU With dDataMovto
Replace E8_SALATUA With nSaldoIni+nEntradas-nSaidas
MsUnlock()
dbSelectArea("SE5")
IF !(SE5->(Eof())) .and. E5_BANCO+E5_AGENCIA+E5_CONTA ==
cBanco+cAgencia+cConta
IF !lAllFil .and. E5_FILIAL != xFIlial("SE5")
Exit
Endif
For nData := dDataMovto+1 to ((SE5->E5_DTDISPO) - 1)
dbSelectArea("SE8")
If dbSeek(cFilial + cBanco+cAgencia+cConta+dtos(nData))
RecLock("SE8",.F.,.T.)
dbDelete()
MsUnlock()
SX2->(MsUnlock())
EndIf
134
dbSelectArea("SE5")
Next
Endif
IF SE5->(Eof()) .or. E5_BANCO+E5_AGENCIA+E5_CONTA != cBanco+cAgencia+cConta
dbSelectArea("SE8")
dbSeek(cFilial + cBanco+cAgencia+cConta+dtos(dDataMovto+1),.t.)
While !Eof() .and. cFilial + cBanco+cAgencia+cConta == ;
E8_FILIAL+E8_BANCO+E8_AGENCIA+E8_CONTA
RecLock("SE8",.F.,.T.)
dbDelete()
MsUnlock()
SX2->(MsUnlock())
dbselectArea("SE8")
dbSkip()
End
Endif
dbSelectArea("SE5")
End // Fecha Primeiro Loop do SE5
dbSelectArea("SA6")
RecLock("SA6")
Replace A6_SALATU With nSaldoIni+nEntradas-nSaidas
MsUnLock()
dbSkip()
End
dbSelectArea("SE5")
RetIndex( "SE5")
Set Filter To
If !Empty(cIndex)
ferase( cIndex+OrdBagExt())
EndIf
Return NIL
/*/
+------------+----------+-------+-----------------------+------+----------+
| Funcao |Fa211Proc | Autor |Wagner Xavier | Data |09.03.2000|
|------------+----------+-------+-----------------------+------+----------+
| Descricao |Funcao de recalculo dos saldos bancarios – TOP CONNECT |
+------------+------------------------------------------------------------+
| Sintaxe | Fa211Proc () |
+------------+------------------------------------------------------------+
| Parametros | Nenhum |
+------------+------------------------------------------------------------+
| Retorno | Nenhum |
+------------+------------------------------------------------------------+
| Uso | FINA210 |
+------------+------------------------------------------------------------+
/*/
#IFDEF TOP
Function FA211Proc()
LOCAL nSaldoIni, nEntradas
LOCAL nSaidas, nData
LOCAL cQuery
LOCAL dDataMovto
+----------------------------------------------------------+
| Variaveis utilizadas para parametros |
| mv_par01 // Do Banco |
| mv_par02 // Ate o Banco |
| mv_par03 // Da Agencia |
| mv_par04 // Ate a Agencia |
| mv_par05 // Da Conta |
| mv_par06 // Ate a Conta |
| mv_par07 // A partir da Data |
+----------------------------------------------------------+
+----------------------------------------------------------------+
| Inicia recalculo de saldos atraves da movimentacao bancaria |
+----------------------------------------------------------------+
cQuery := "SELECT SA6.R_E_C_N_O_ A6_RECNO,"
cQuery += " E5_BANCO, E5_AGENCIA, E5_CONTA, E5_DTDISPO, E5_TIPODOC, E5_MOEDA,"
cQuery += " E5_NUMCHEQ, E5_MOTBX, E5_NUMERO, E5_RECPAG, E5_VALOR, E5_DOCUMEN"
cQuery += " FROM " + RetSqlName("SA6") + " SA6, " + RetSqlName("SE5") + " SE5"
cQuery += " WHERE A6_FILIAL = '" + xFilial("SA6") + "'"
cQuery += " AND A6_COD between '" + mv_par01 + "' AND '" + mv_par02 + "'"
135
cQuery += " AND A6_AGENCIA between '" + mv_par03 + "' AND '" + mv_par04 + "'"
cQuery += " AND A6_NUMCON between '" + mv_par05 + "' AND '" + mv_par06 + "'"
cQuery += " AND SA6.D_E_L_E_T_ <> '*'"
cQuery += " AND E5_VENCTO <= E5_DATA"
cQuery += " AND A6_COD = E5_BANCO"
cQuery += " AND A6_AGENCIA = E5_AGENCIA"
cQuery += " AND A6_NUMCON = E5_CONTA"
cQuery += " AND E5_SITUACA <> 'C'"
cQuery += " AND E5_TIPODOC <> 'BA'"
cQuery += " AND SE5.D_E_L_E_T_ <> '*'"
If Empty(xFilial( "SA6")) .AND. !Empty(xFilial("SE5"))
cQuery += " AND E5_DTDISPO >= '" + dtos(mv_par07) + "'"
//O filtro de filial entre ' ' e 'ZZ' foi adicionado para o SQL utilizar indice
cQuery += " AND E5_FILIAL between ' ' AND 'ZZ'"
Else
cQuery += " AND E5_DTDISPO >= '" + dtos(mv_par07) + "' AND E5_FILIAL = '" +
xFilial("SE5") + "'"
Endif
cQuery += " ORDER BY E5_BANCO, E5_AGENCIA, E5_CONTA, E5_DTDISPO"
cQuery := ChangeQuery(cQuery)
dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),'TRB210',.T.,.T.)
TcSetField("TRB210", "E5_DTDISPO", "D")
While !Eof()
dbSelectArea("TRB210")
cBanco := E5_BANCO
cAgencia := E5_AGENCIA
cConta := E5_CONTA
nSaldoIni:= 0
nEntradas:= 0
nSaidas := 0
+---------------------------------------------------------+
| Localiza Saldo de Partida. |
| Observe que o programa retorna um registro no banco de |
| dados, portanto a data de referencia ‚ a data em que |
| o saldo ficou errado, nao a data correta do saldo. |
+---------------------------------------------------------+
dbSelectArea( "SE8" )
dbSeek( cFilial+cBanco+cAgencia+cConta+Dtos(mv_par07),.T. )
dbSkip( -1 )
If E8_BANCO != cBanco .or. E8_AGENCIA != cAgencia .or. E8_CONTA != cConta .or.
BOF() .or. EOF()
nSaldoIni := 0
Else
nSaldoIni := E8_SALATUA
Endif
+----------------------------------------------------------------+
| Localiza movimentacao bancaria |
+----------------------------------------------------------------+
dbSelectArea("TRB210")
While !Eof() .and. E5_BANCO+E5_AGENCIA+E5_CONTA == cBanco+cAgencia+cConta
dDataMovto := E5_DTDISPO
While !Eof() .and. E5_BANCO+E5_AGENCIA+E5_CONTA+DTOS(E5_DTDISPO) == ;
cBanco+cAgencia+cConta+dtos(dDataMovto)
IF E5_TIPODOC $ "DC/JR/MT/CM/D2/J2/M2/C2/V2/CP/TL" //Valores de Baixas
dbSkip()
Loop
Endif
If E5_MOEDA $ "C1/C2/C3/C4/C5" .and. Empty(E5_NUMCHEQ)
dbSkip()
Loop
Endif
+---------------------------------------------------------------+
| Na transferencia somente considera nestes numerarios |
| No Fina100 ‚ tratado desta forma. |
| As transferencias TR de titulos p/ Desconto/Cau‡Æo (FINA060) |
| nÆo sofrem mesmo tratamento dos TR bancarias do FINA100 |
+---------------------------------------------------------------+
If E5_TIPODOC $ "TR/TE" .and. Empty(E5_NUMERO)
If !(E5_MOEDA $ "R$/DO/TB/TC/CH")
dbSkip()
136
Loop
Endif
Endif
If E5_TIPODOC $ "TR/TE" .and. (Substr(E5_NUMCHEQ,1,1)=="*" ;
.or. Substr(E5_DOCUMEN,1,1) == "*" )
dbSkip()
Loop
Endif
If E5_MOEDA == "CH" .and. IsCaixaLoja(E5_BANCO) //Sangria
dbSkip()
Loop
Endif
If SubStr(E5_NUMCHEQ,1,1)=="*" //cheque para juntar (PA)
dbSkip()
Loop
Endif
If !Empty(E5_MOTBX)
If !MovBcoBx(E5_MOTBX)
dbSkip()
Loop
Endif
Endif
If E5_RECPAG = "R"
nEntradas += E5_VALOR
Else
nSaidas += E5_VALOR
Endif
dbSkip()
End // Quebra da data
dbSelectArea("SE8")
dbSeek(cFilial+cBanco+cAgencia+cConta+Dtos(dDataMovto))
IF Eof()
RecLock("SE8",.t.)
Else
RecLock("SE8",.f.)
Endif
Replace E8_FILIAL With cFilial,;
E8_BANCO With cBanco,;
E8_AGENCIA With cAgencia,;
E8_CONTA With cConta,;
E8_DTSALATU With dDataMovto
Replace E8_SALATUA With nSaldoIni+nEntradas-nSaidas
MsUnlock()
dbSelectArea("TRB210")
IF !(TRB210->(Eof())) .and. E5_BANCO+E5_AGENCIA+E5_CONTA ==
cBanco+cAgencia+cConta
For nData := dDataMovto+1 to ((E5_DTDISPO) - 1)
dbSelectArea("SE8")
If dbSeek(cFilial + cBanco+cAgencia+cConta+dtos(nData))
RecLock("SE8",.F.,.T.)
dbDelete()
MsUnlock()
SX2->(MsUnlock())
EndIf
dbSelectArea("TRB210")
Next
Endif
If TRB210->(Eof()) .or. E5_BANCO+E5_AGENCIA+E5_CONTA !=
cBanco+cAgencia+cConta
dbSelectArea("SE8")
dbSeek(cFilial+cBanco+cAgencia+cConta+dtos(dDataMovto+1),.t.)
While !Eof() .and. cFilial+cBanco+cAgencia+cConta == ;
E8_FILIAL+E8_BANCO+E8_AGENCIA+E8_CONTA
RecLock("SE8",.F.,.T.)
dbDelete()
MsUnlock()
SX2->(MsUnlock())
dbselectArea("SE8")
dbSkip()
Enddo
Endif
137
dbSelectArea("TRB210")
Enddo // Fecha Primeiro Loop do SE5
dbSelectArea("SA6")
If dbSeek( xFilial("SA6")+cBanco+cAgencia+cConta)
RecLock("SA6")
Replace A6_SALATU With nSaldoIni+nEntradas-nSaidas
MsUnLock()
EndIf
dbSelectArea("TRB210")
dbSkip()
Enddo
dbSelectArea("TRB210")
dbCloseArea()
Return NIL
#ENDIF
138
AAdd
Adiciona um novo elemento ao final do array.
Si n t a x e
expValor Sim Todos É uma expressão válida que será o valor do novo elemento.
Retorno Descrição
avalia expValue e retorna seu Valor. Se expValue não for especificado, AADD() retorna
AADD()
NIL.
D es c r i ç ã o
AADD() é uma função de array que incrementa o tamanho real do array aAlvo em um. O elemento de
array recentemente criado é atribuído o Valor especificado por ex pValue.
AADD() é usado para aumentar dinâmicamente uma array. É útil para listas ou filas criadas
dinamicamente.
Um exemplo bom deste é o GetList, array usada pelo sistema para armazenar objetos do tipo Get. Depois
que um READ ou CLEAR GETS é executado, a GetList ficará vazia. Cada vez que você executa um
comando @...GET, o sistema usa AADD() para adicionar um novo elemento à array GetList, e atribui
então um novo objeto GET ao novo elemento.
AADD() é similar a ASIZE(), mas apenas adiciona um elemento por vez; ASIZE() pode incrementar ou
decrementar uma array a um determinado tamanho. AADD(), entretanto, têm a vantagem de poder
atribuir um valor ao elemento recentemente adicionado, enquanto que ASIZE() não pode. AADD() pode
também parecer similar a AINS(), mas é diferente: AINS() move elementos dentro de uma disposição,
mas os ele não muda o tamanho.
139
Se ex pValue for uma outra array, o novo elemento em aAlvo conterá uma referência à array
especificada por ex pValue.
Ex e m p l o s
ACopy
Si n t a x e
Retorno Descrição
140
D es c r i ç ã o
ACOPY() é uma função de array que copia elementos do array aOrige m para array aDestino. O array
destino aDestino já deve ter sido declarado e grande o bastante para conter os elementos que serão
copiados.
Se o array aOrige m contiver mais elementos, alguns dos elementos não serão copiados. ACOPY() copia os
valores de todos os dados, incluindo valores nulos (NIL) e códigos de bloco.
Ex e m p l o s
Este exemplo cria dois arrays, com um conteúdo cada. Os dois primeiros elementos do array
fonte são então copiados no array destino:
LOCAL nCount := 2, nStart := 1, aOne, aTwo
aOne := { 1, 1, 1 }
aTwo := { 2, 2, 2 }
ACOPY(aOne, aTwo, nStart, nCount)
// Result: aTwo is now { 1, 1, 2 }
AClone
Duplica arrays aninhadas ou multi-dimensionais.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
ACLONE() é uma função de array, que cria duplicatas completas do array aSource. Se aSource contiver
arrays aninhadas, ACLONE() criará o mesmo padrão de aninhamento preenchendo com cópias dos valores
contidos em aSou rce.
141
ACLONE() é similar a ACOPY(), exceto que ACOPY() não duplica arrays aninhadas.
Ao igualarmos dois arrays, eles ficam associados por referência, utilizando aClone() não existe referência.
Ex e m p l o s
ADel
Exclui um elemento de um array.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
ADEL() é uma função de manipulação que elimina uma posição do array, deslocando as posições
posteriores. A última posição do array passa a ter o conteúdo NIL.
Ex e m p l o s
LOCAL aArray
aArray := { 1, 2, 3 } // Resultado: { 1, 2, 3 }
ADEL(aArray, 2) // Resultado: { 1, 3, NIL }
ADir
142
Si n t a x e
ADIR([ cArqEspec ], [ aNomeArq ], [ aTa manho ], [ aDa ta ], [ aHora ], [ aAt rib uto ]) --> Numérico
Retorno Descrição
D es c r i ç ã o
ADir() preenche os arrays passados com os dados dos arquivos encontrados, através da máscara
informada. Tanto arquivos locais (Remote) como do servidor podem ser informados. ADir é uma função
obsoleta, utilize sempre Directory().
Ex e m p l o s
LOCAL aFiles[ADIR("*.TXT")]
ADIR("*.TXT", aFiles)
AEVAL(aFiles, { |element| QOUT(element) })
AEval
143
Si n t a x e
Retorno Descrição
D es c r i ç ã o
AEVAL() executa um code block para cada elemento de um array, passando cada um como o parâmetro
do bloco. É muito semelhante ao DBEVAL().
AEVAL() passa cada elemento de um array para o code block sem se preocupar com o tipo.
Ex e m p l o s
// Exemplo 1
#include "Directry.ch"
//
LOCAL aFiles := DIRECTORY("*.dbf"), nTotal := 0
AEVAL(aFiles,{ | aDbfFile | QOUT(PADR(aDbfFile[F_NAME], 10), aDbfFile[F_SIZE]),;
nTotal += aDbfFile[F_SIZE]);
} )
//
?
? "Total Bytes:", nTotal
// Exemplo 2
#include "Directry.ch"
//
LOCAL aFiles := DIRECTORY("*.dbf"), aNames := {}
AEVAL(aFiles, { | file | AADD(aNames, file[F_NAME]) } )
//Exemplo 3
LOCAL aArray[6]
AFILL(aArray,"old")
AEVAL(aArray,;
{|cValue,nIndex| IF(cValue == "old",;
aArray[nIndex] := "new",)})
144
EVAL()
DBEVAL()
AFill
Preenche um array com um determinado valor.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
AFILL() é função de manipulação de arrays, que preenche os elementos do array com qualquer tipo de
dado. Incluindo code block.
Afill() não deve ser usado para preencher um array com outro array.
Ex e m p l o s
LOCAL aLogic[3]
// Resultado: aLogic é { NIL, NIL, NIL }
AFILL(aLogic, .F.)
// Resultado: aLogic é { .F., .F., .F. }
AFILL(aLogic, .T., 2, 2)
// Resultado: aLogic é { .F., .T., .T. }
145
A I ns
Insere um elemento com conteúdo NIL em um array.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
AINS() é um função de manipulação de array que insere um elemento na posição determinada por nPos.
O novo elemento possui conteúdo igual a NIL. Após a inserção, o último elemento será excluído.
Ex e m p l o s
LOCAL aArray
aArray := { 1, 2, 3 } // Resultado: { 1, 2, 3 }
AINS(aArray, 2) // Resultado: { 1, NIL, 2 }
Alias
Verifica qual é o Alias.
Si n t a x e
146
Retorno Descrição
D es c r i ç ã o
Verifica qual é o Alias de determinada área de trabalho; se ela não foi especificada, será verificado qual o
Alias da área de trabalho corrente. O Alias é definido quando a tabela é aberta através do parâmetro
correspondente (DBUSEAREA()).
Esta função é o inverso da função SELECT(), pois nesta é retornado o número da área de trabalho do
Alias correspondente.
Ex e m p l o
// Este exemplo mostra como o Alias corrente pode ser apresentado para o usuário.
dbUseArea( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
MessageBox("O Alias corrente é: " + Alias(), "Alias", 0) // Resultado: "O Alias
corrente é: SSS"
Append From
Importa registros de outra tabela ou arquivo texto.
Si n t a x e
APPEND FROM Arquivo [FIELDS Campos] [FOR CondFor] [WHILE CondWhile] [NEXT nRecs] [RECORD
nRecno] [REST] [ALL] [VIA RDD] [SDF | DELIMITED [WITH BLANK | cDeli mitador] ]
147
.F.).
Não
nRecs N Quantos registros devem ser copiados.
D es c r i ç ã o
Este comando é utilizado para copiar alguns registros do arquivo especificado por "FROM cArquiv o"
utilizando-se o driver especificado por "VIA RDD" se especificado.
Se forem especificados os campos de interesse através de "FIELDS Ca mpos", apenas eles serão copiados,
caso contrário todos campos o serão. Se não forem especificadas as condições para que o registro seja
copiado, copia toda a tabela como se estivesse especificada a opção "ALL".
Pode-se especificar um escopo para que os registros sejam copiados através das opções "FOR CondFor" e
"WHILE CondWhile". Pode-se também limitar o número de registros a serem copiados através da opção
"NEXT nRecs" e determinar que a cópia dos registros deve-se iniciar a partir do registro atual com "REST",
mas caso contrário o comando executa um DBGOTOP() antes de iniciar a cópia. Se é desejado copiar
apenas determinado registro pode-se defini-lo através da especificação do recno com "RECORD nRecno".
Além de copiar registros de uma tabela normal, pode-se copiar registros de um arquivo texto que
contenha os dados desejados. Existem duas formas de gerar estes arquivos textos com COPY TO,
utilizando-se o SDF que trabalha com tamanhos de registros e campos fixos (preenchendo com espaços)
ou através de um delimitador que separa os campos",". Deve-se especificar na cópia qual o tipo do
arquivo texto através das opções "SDF" ou "DELIMITED".
Pode-se ainda especificar qual o delimitador utilizado nas strings da seguinte forma:
Caso seja omitido o delimitador será considerado o delimitador padrão (" ").
Ex e m p l o
// Este exemplo demonstra como utilizar o comando APPEND FROM para acrescentar alguns
campos de registros (apenas 10 registros) de outra tabela pertencentes a um escopo
definido a partir do registro atual para a tabela corrente:
USE Cliente VIA "CTREECDX" NEW
148
APPEND FROM Amigos FIELDS Nome,Nascimento,End,Tel FOR Idade>20 WHILE Nome<"VVV" NEXT 10
REST
// Este exemplo demonstra como se pode utilizar o comando <@>COPY TO para gravar os dados
de uma tabela em um arquivo do tipo texto (DELIMITED) e incluí-los a outra tabela com o
comando APPEND FROM:
USE Amigos NEW
COPY TO temp DELIMITED // Registro: "Jose",19751108,69411233,12.00
COPY TO temp1 DELIMITED WITH BLANK // Registro: Jose 19751108 69411233 12.00
COPY TO temp2 DELIMITED WITH "@" // Registro: @Jose@,19751108,69411233,12.00
USE Cliente NEW
APPEND FROM temp DELIMITED
USE Cliente1 NEW
APPEND FROM temp1 DELIMITED WITH BLANK
USE Cliente2 NEW
APPEND FROM temp2 DELIMITED WITH "@"
// Este exemplo demonstra como se pode utilizar o comando <@>COPY TO para gravar os dados
de uma tabela em um arquivo do tipo texto (SDF) e incluí-los a outra tabela com o comando
APPEND FROM:
USE Amigos NEW
COPY TO temp3 SDF // Registro: Jose 1975110869411233 12.00
USE Cliente3 NEW
APPEND FROM temp3 SDF
Array
Cria um array com dados não inicializados.
Si n t a x e
ARRAY( nQt dEle men tos1 , [ nQt dEle men tosn ]...) --> aArray
Retorno Descrição
D es c r i ç ã o
Array() é uma função que retorna um array não inicializado com múltiplas dimensões.
A vantagem de utilizar ARRAY(), ao invés de outras opções, é a possibilidade de usá-la em code blocks e
expressões.
149
Ex e m p l o
AScan
Busca em um array até que o bloco retorne verdadeiro .T.
Si n t a x e
Argumento Descrição
<expSearch> Obrigatório, Qualquer Tipo. Casis either a simple value to scan for, or a code block.
numeric type.
Returns
ASCAN() returns a numeric value representing the array position of thelast element scanned. If
<expSearch> is a simple value, ASCAN() returnsthe position of the first matching element, or zero if a
match is notfound. If <expSearch> is a code block, ASCAN() returns the position ofthe element where the
block returned true (.T.).
Description
150
ASCAN() is an array function that scans an array for a specified valueand operates like SEEK when
searching for a simple value. The<expSearch> value is compared to the target array element beginning
withthe leftmost character in the target element and proceeding until thereare no more characters left in
<expSearch>. If there is no match,ASCAN() proceeds to the next element in the array.Since ASCAN()
uses the equal operator (=) for comparisons, it issensitive to the status of EXACT. If EXACT is ON, the
target arrayelement must be exactly equal to the result of <expSearch> to match.If the <expSearch>
argument is a code block, ASCAN() scans the <aTarget>array executing the block for each element
accessed. As each element isencountered, ASCAN() passes the element's value as an argument to thecode
block, and then performs an EVAL() on the block. The scanningoperation stops when the code block
returns true (.T.), or ASCAN()reaches the last element in the array.
Examples
simple values and a code block as search criteria. The code block
//
== "MARY" }) // Result: 2
"Mary" }, nStart := 1
//
nAtEnd := LEN(aArray)
nStart)) > 0
? nPos, aArray[nPos]
//
// boundary condition
EXIT
ENDIF
ENDDO
151
LOCAL aArr:={}
CLS
AADD(aArr,{"one","two"})
AADD(aArr,{"three","four"})
AADD(aArr,{"five","six"})
See Also
AEVAL()
EVAL()
ASize
Acrescenta ou reduz elementos de um array.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
ASIZE() é uma função de manipulação de array que aumenta ou diminui o tamanho de um array.
No caso de diminuição, os últimos elementos serão apagados, em caso de aumento de tamanho, os novos
elementos terão conteúdo NIL.
Ex e m p l o s
152
ASor t
Ordena um array.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
ASORT() é uma função de manipulação de array que classifica todo ou parcialmente um array de tipo
simples. Os tipos que podem ser classificados automaticamente são: caracter, data, lógico e numérico.
Caso bOrder seja especificado, o code block será usado para ordernar o array, neste caso, pode-se usar
dados de qualquer tipo. Cada vez que o bloco for avaliado, serão passados dois elementos do array, caso
eles estejam em ordem, deve-se retornar .T.
Ex e m p l o s
// Exemplo 1
aArray := { 3, 5, 1, 2, 4 }
ASORT(aArray)
153
// Resultado: { 1, 2, 3, 4, 5 }
ASORT(aArray,,, { |x, y| x > y })
// Resultado: { 5, 4, 3, 2, 1 }
//Exemplo 2
aArray := { "Fred", Kate", "ALVIN", "friend" }
ASORT(aArray,,, { |x, y| UPPER(x) < UPPER(y) })
//Exemplo 3
aKids := { {"Mary", 14}, {"Joe", 23}, {"Art", 16} }
aSortKids := ASORT(aKids,,, { |x, y| x[2] < y[2] })
Resultado:
{ {"Mary", 14}, {"Art", 16}, {"Joe", 23} }
ATail
Retorna o último elemento de um array
Si n t a x e
Retorno Descrição
D es c r i ç ã o .
ATAIL() é uma função de manipulação de array que retorna o último elemento de um array. Ela deve ser
usada em substituição da seguinte construção: aAr ray [LEN( aAr ray )]
Ex e m p l o s
BTVCanOpen
Verifica se a tabela BTrieve pode ser aberta.
Si n t a x e
154
Retorno Descrição
Não é possível abrir a tabela testada. Principais motivos: Não existe o arquivo da
.F. tabela ou do índice fisicamente, ou as definições da tabela ou índice em questão
não foram encontradas.
D es c r i ç ã o
Esta função verifica se a tabela definida pelo parâmetro cNom e pode ser aberta e, se existir, o parâmetro
cIndice verifica, também, se o índice pode ser aberto. Para tanto, é testado se os arquivos envolvidos
existem fisicamente, caso afirmativo, é verificado se as definições envolvidas são encontradas nos
arquivos do DDF's.
Ex e m p l o
BTVCreateDDFs
Gera os arquivos de definições (DDF´s) compatíveis com outras ferramentas que manipulam arquivos
Btrieve (Crystal Reports).
Si n t a x e
cDiretorio Não C Nome do diretório (abaixo do root) onde serão criados os novos
DDF's.
155
Retorno Descrição
.T.
Transformação de definições ocorrida com sucesso.
D es c r i ç ã o
Esta função transforma as informações armazenadas nos arquivos DDF's para o padrão utilizado por
outras ferramentas, principalmente para geração de relatórios. Sendo que podem ser selecionadas apenas
as tabelas de interesse através do parâmetro aTabelas.
Se o diretório não for especificado, será utilizado o diretório definido no arquivo FILE.BTV.
Ex e m p l o
// Este exemplo demonstra o uso típico de BTVCreateDDFs(). Se não falhar, serão gerados
os novos arquivos de definição. Se falhar, uma mensagem é apresentada.
b:= {{"AA3990"}, {"SA1990", "c:\protheus507\dadosadv"}}
IF !BTVCreateDDFs(b, "\temp") // Será concatenado com o RootPath
Messagebox("Não foi possível montar o array com os nomes das tabelas","Erro", 0)
BREAK
ENDIF
BTVDrop I dxs
Apaga os índices da tabela corrente.
Si n t a x e
BTVDropIdxs ()->Lógico
Retorno Descrição
Não conseguiu apagar os índices. Principais er ros : RDD não é Bt rieve, não achou as definições
.F.
no DDF, o arquiv o não está exclusivo
156
D es c r i ç ã o
A função BTVDropIdxs apaga os índices da tabela corrente, com exceção do índice interno, apenas se
o mesmo for Btrieve e estiver aberto exclusivo. Para tanto ela executa os seguintes passos:
3. Apaga os índices do arquivo da tabela corrente. Todos os índices criados de forma permanente
ficam guardados na estrutura da tabela. Quando a tabela for aberta, todos os índices criados de
forma permanente e o índice interno serão abertos também. Por isso, é recomendada a criação de
índices de forma temporária.
Ex e m p l o
// Este exemplo demonstra o uso típico de BTVDropIdxs(). Se não falhar, os índices são
apagados e o processo continua. Se falhar, uma mensagem é apresentada.
USE Clientes SHARED NEW
IF !BTVDropIdxs()
Messagebox("Não foi possível deletar os índices da tabela corrente","Erro", 0)
BREAK
ENDIF
BTVTables
Retorna array composto por nomes das tabelas definidas no DDF do Protheus (FILE.BTV).
Si n t a x e
BTVTables ()-->Array
Retorno Descrição
NIL Não conseguiu montar o ar ray . Principais er ros: RDD não é Btrieve ou
não conseg uiu recuperar as informações cor retamente do arq uivo
FILE.BTV do DDFs.
D es c r i ç ã o
Verifica todos os nomes das tabelas armazenados no arquivo FILE.BTV do DDF e retorna um array com
todos eles. Toda tabela criada possui o nome acrescentado neste arquivo de definições.
Ex e m p l o
// Este exemplo demonstra o uso típico de BTVTables(). Se não falhar, é montado um array
com os nomes das tabelas e esses nomes são mostrados no servidor. Se falhar, uma mensagem
é apresentada.
157
a:= BTVTables()
IF a=Nil
Messagebox("Não foi possível montar o array com os nomes das tabelas","Erro", 0)
BREAK
ELSE
FOR i:= 1 to LEN(a)
ConOut(a[i])
NEXT
ENDIF
CDo w
Converte uma data para uma cadeia de caracteres contendo o dia da semana.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
CDOW() é uma função que converte uma data para uma cadeia de caracteres.
Ex e m p l o s
CMon t h
Converte uma data para uma cadeia de caracteres contento o nome do mês.
Si n t a x e
158
Retorno Descrição
D es c r i ç ã o
CMONTH() é uma função de conversão de datas que retorna uma cadeia de caracteres com o nome do
mês em inglês.
Ex e m p l o s
Commit
Salva em disco as modificações de todas as tabelas.
Si n t a x e
COMMIT
D es c r i ç ã o
Este comando salva em disco todas as atualizações pendentes em todas as áreas de trabalho.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o COMMIT para salvar todas as alterações
realizadas nas áreas de trabalho abertas no momento.
USE Clientes NEW
DBGOTO(100)
Nome := "Jose"
USE Fornecedores NEW
DBGOTO(168)
Nome := "Joao"
COMMIT// Salva em disco as alterações realizadas nas tabelas Clientes e Fornecedores
159
Copy To
Copia registros da tabela corrente para uma nova tabela.
Si n t a x e
COPY TO Arq uivo [FIELDS Campos] [FOR CondFor] [WHILE CondWhile] [NEXT nRecs] [RECORD nRecno]
[REST] [ALL] [VIA RDD] [SDF | DELIMITED [WITH BLANK | cDeli mitador] ]
D es c r i ç ã o
Este comando é utilizado para copiar alguns registros da tabela corrente para o arquivo especificado por
"TO cArq uivo" utilizando-se o driver especificado por "VIA RDD" se especificado. Se forem especificados os
campos de interesse através de "FIELDS Ca mpos" apenas eles serão copiados, caso contrário todos
campos o serão. Se não forem especificadas as condições para que o registro seja copiado, copia toda a
tabela como se estivesse especificada a opção "ALL".
Pode-se especificar um escopo para que os registros sejam copiados através das opções "FOR CondFor" e
"WHILE CondWhile". Pode-se também limitar o número de registros a serem copiados através da opção
"NEXT nRecs" e determinar que a cópia dos registros deve-se iniciar a partir do registro atual com "REST",
mas caso contrário o comando executa um DBGOTOP() antes de iniciar a cópia. Se é desejado copiar
apenas determinado registro pode-se defini-lo através da especificação do recno com "RECORD nRecno".
160
Além de copiar registros para uma tabela normal, pode-se copiar registros para um arquivo texto que
contenha os dados desejados. Existem duas formas de gerar estes arquivos textos com COPY TO,
utilizando-se o SDF que trabalha com tamanhos de registros e campos fixos (preenchendo com espaços)
ou através de um delimitador que separa os campos",". Deve-se especificar na cópia qual o tipo do
arquivo texto através das opções "SDF" ou "DELIMITED". Pode-se ainda especificar qual o delimitador
utilizado nas strings da seguinte forma:
Caso seja omitido, o delimitador será considerado o delimitador padrão (" ").
Ex e m p l o
// Este exemplo demonstra como utilizar o comando COPY TO criar nova tabela com alguns
campos escolhidos e alguns registros (apenas 10) da tabela atual pertencentes a um escopo
definido a partir do registro atual para determinada tabela:
USE Cliente VIA "CTREECDX" NEW
COPY TO Amigos FIELDS Nome,Nascimento,End,Tel FOR Idade>20 WHILE Nome<"VVV" NEXT 10 REST
// Este exemplo demonstra como se pode utilizar o comando COPY TO para gravar os dados de
uma tabela em um arquivo do tipo texto (DELIMITED) e incluí-los a outra tabela com o
comando APPEND FROM:
USE Amigos NEW
COPY TO temp DELIMITED // Registro: "Jose",19751108,69411233,12.00
COPY TO temp1 DELIMITED WITH BLANK // Registro: Jose 19751108 69411233 12.00
COPY TO temp2 DELIMITED WITH "@" // Registro: @Jose@,19751108,69411233,12.00
USE Cliente NEW
APPEND FROM temp DELIMITED
USE Cliente1 NEW
APPEND FROM temp1 DELIMITED WITH BLANK
USE Cliente2 NEW
APPEND FROM temp2 DELIMITED WITH "@"
// Este exemplo demonstra como se pode utilizar o comando <@>COPY TO para gravar os dados
de uma tabela em um arquivo do tipo texto (SDF) e incluí-los a outra tabela com o comando
APPEND FROM:
USE Amigos NEW
COPY TO temp3 SDF // Registro: Jose 1975110869411233 12.00
USE Cliente3 NEW
APPEND FROM temp3 SDF
Copy File
Copia Arquivos.
Si n t a x e
161
Retorno Descrição
D es c r i ç ã o
Caso a origem esteja no cliente e o destino no servidor os arquivos são copiados para o servidor, o
contrário também é valido.
Ex e m p l o
Si n t a x e
D es c r i ç ã o
Este comando é utilizado para criar nova tabela copiando a estrutura da tabela atual, sendo que pode-se
selecionar apenas os campos de interesse através da opção "FIELD Ca mpos" que se omitida, deixa que o
comando copie toda a estrutura.
162
Ex e m p l o
// Este exemplo demonstra como utilizar o comando COPY STRUCTURE no seu modo mais usual:
USE Cliente NEW
COPY STRUCTURE FIELDS Nome,Idade TO NovoCliente
// Este exemplo demonstra como o comando COPY STRUCTURE pode substituir o DBCREATE:
USE Cliente NEW
COPY STRUCTURE TO NovoCliente
// *** é semelhante a ***
USE Cliente NEW
DBCREATE("NovoCliente",DBSTRUCT())
CPYS2T
Copia arquivos do servidor para o cliente ( Remote ).
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Copia um arquivo, do servidor para o cliente ( Remote ), os caracteres * e ?, são aceitos normalmente.
Caso a compactação seja habilitada ( lCompacta ), os dados serão transmitidos de maneira compactada e
descompactados antes do uso.
Ex e m p l o
163
CPYT2S
Copia Arquivos entre o Cliente ( Terminal ) para o servidor.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Copia um arquivo, do cliente ( Remote ) para o servidor, os caracteres * e ?, são aceitos normalmente.
Caso a compactação seja habilitada ( lCo mpacta ), os dados serão transmitidos de maneira compacta e
descompactados antes do uso.
Ex e m p l o
CTreeDel I dxs
164
Si n t a x e
CTreeDelIdxs()->Lógico
Retorno Descrição
.F. Não conseg uiu deletar os índices. Principais er ros: RDD não é Ctre ; não
fechou a tabela ; não apagou o arq uivo de índice ; não at ualizou as
informações da tabela ; não ab riu a tabela novamente.
D es c r i ç ã o
A função CtreeDelIdxs apaga os índices da tabela corrente, com exceção do índice interno, apenas se
o mesmo for CTree e estiver exclusiva. Para tanto, ela executa os seguintes passos:
2. Fecha a tabela;
Todos os índices criados de forma permanente ficam guardados na estrutura da tabela. Portanto, não
adianta deletar os arquivos de índices, pois quando a tabela for aberta, todos os índices criados de forma
permanente e o índice interno serão recriados fisicamente (se não existirem); caso contrário, a tabela não
será aberta. Por isso, é recomendada a criação de índices de forma temporária.
Ex e m p l o
// Este exemplo demonstra o uso típico de CtreeDelIdxs(). Se não falhar, os índices são apagados e o
processo continua. Se falhar, uma mensagem é apresentada.
CTreeDelln t
Deleta índice interno da tabela CTree.
Si n t a x e
165
cNome Sim C Especifica o nome da tabela cujo índice interno deve ser
deletado.
Retorno Descrição
Não conseguiu deletar o índice interno. Principais erros: tabela não está
.F. dentro do diretório do Protheus; não abriu a tabela ou não deletou o
arquivo de índice interno.
D es c r i ç ã o
A função CtreeDelInt apaga o índice interno de tabela Ctree, estando a mesma fechada. Para tanto,
são executados os seguintes procedimentos:
3. Fecha a tabela;
Ex e m p l o
CurDir
Retorna o diretório corrente.
Si n t a x e
166
Retorno Descrição
D es c r i ç ã o
Retorna o diretório corrente do servidor, caso seja passado um caminho como parâmetro, esse diretório
passará a ser o default.
Ex e m p l o
? CURDIR("C:\TEMP")
Date
Retorna a data do sistema.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
DATE() é a função que retorna a data do atual sistema. O formato de saída é controlado pelo comando
SET DATE. O formato padrão é mm/dd/yy.
Ex e m p l o s
Day
Retorna o dia do mês como valor numérico.
Si n t a x e
167
Retorno Descrição
D es c r i ç ã o
DAY() é uma função de conversão de datas usada para converter o valor data em um número inteiro que
representa o dia do mês.
Esta função pode ser usada em conjunto com CMONTH() e YEAR() para formatar datas. Pode ser usada
também em diversos cálculos envolvendo datas.
Ex e m p l o s
DBAppend
Acrescenta um novo registro na tabela corrente.
Si n t a x e
lLiberaBloq ueios Não L Libera todos os registros bloqueados (locks), valor padrão é .T.
168
D es c r i ç ã o
Esta função acrescenta mais um registro em branco no final da tabela corrente, sempre é acrescentado e
bloqueado. Se o parâmetro estiver com valor .T., todos os bloqueios de registros anteriores são liberados
para que o novo registro seja acrescentado, caso contrário, se for .F., todos os bloqueios anteriores são
mantidos.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o dbappend liberando e mantendo bloqueios
anteriores.
USE Clientes NEW
FOR i:=1 to 5
DBAPPEND(.F.)
NOME := "XXX"
END : "YYY"
NEXT
// Os 5 registros incluídos permanecem bloqueados
DBAPPEND()
// Todos os bloqueios anteriores são liberados
DBClearAllFil ter
Limpa a condição de filtro de todas as ordem as ordens da lista.
Si n t a x e
DBClearAllFilter() ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função salva as atualizações realizadas e pendentes de todas as tabelas e depois limpa as condições
de filtro de todas as ordens inclusas na lista. Seu funcionamento é oposto ao comando SET FILTER.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar DBCLEARALLFILTER para limpar a expressão
de filtro.
USE Clientes NEW
DBSETFILTER( {|| Idade < 40}, "Idade < 40" ) // Seta a expressão de filtro
...
DBCLEARALLFILTER() // Limpa a expressão de filtro de todas as ordens
169
DBClearFil ter
Limpa a condição de filtro.
Si n t a x e
DBClearFilter () ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função salva as atualizações realizadas e pendentes na tabela corrente e depois limpa todas as
condições de filtro da ordem ativa no momento. Seu funcionamento é oposto ao comando SET FILTER.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar DBCLEARFILTER para limpar a expressão de
filtro.
USE Clientes NEW
DBSETFILTER( {|| Idade < 40}, "Idade < 40" ) // Seta a expressão de filtro
...
DBCLEARFILTER() // Limpa a expressão de filtro
DBCloseAll
Fecha todas as tabelas abertas.
Si n t a x e
DBCloseAll () ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função salva as atualizações pendentes, libera todos os registros bloqueados e fecha todas as tabelas
abertas (áreas de trabalho) como se chamasse DBCLOSEAREA para cada área de trabalho.
Ex e m p l o
170
// Este exemplo demonstra como se pode utilizar o DBCLOSEALL para fechar a área de
trabalho atual.
USE Clientes NEW
DBSETINDEX("Nome") // Abre o arquivo de índice "Nome"
USE Fornecedores NEW
DBSETINDEX("Idade") // Abre o arquivo de índice "Idade"
...
DBCLOSEALL() // Fecha todas as áreas de trabalho, todos os indices e ordens
DBCloseArea
Fecha a área de trabalho.
Si n t a x e
DBCloseArea () ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função salva as atualizações pendentes na tabela corrente, libera todos os registros bloqueados e
fecha a tabela corrente (área de trabalho). Seu funcionamento é semelhante ao comando CLOSE e é
oposto à função DBUSEAREA e ao comando USE.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBCLOSEAREA para fechar a área de
trabalho atual.
USE Clientes NEW
DBSETINDEX("Nome") // Abre o arquivo de índice "Nome"
...
DBCLOSEAREA() // Fecha a área de trabalho atual, todos os indices e ordens
DBClear I ndex
Fecha todos os arquivos de índice da área de trabalho.
Si n t a x e
DBClearIndex () ->Nil
Retorno Descrição
NIL Nenhum
171
D es c r i ç ã o
Esta função salva as atualizações pendentes na tabela corrente e fecha todos os arquivos de índice da
área de trabalho, por conseqüência limpa todas as ordens da lista. Seu funcionamento é oposto ao
comando <@>SET INDEX.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar a função DBCLEARINDEX para fechar os
índices.
USE Clientes NEW
DBSETINDEX("Nome") // Abre o arquivo de índice "Nome"
...
DBCLEARINDEX() // Fecha todos os arquivos de índices
DBCommit
Salva em disco todas as modificações da tabela corrente.
Si n t a x e
DBCommit() ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função salva em disco todas as atualizações pendentes na área de trabalho corrente.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBCOMMIT para salvar todas as
alterações realizadas na área de trabalho atual.
USE Clientes NEW
DBGOTO(100)
Nome := "Jose"
USE Fornecedores NEW
DBGOTO(168)
Nome := "Joao"
DBCOMMIT() // Salva em disco apenas as alterações realizadas na tabela Fornecedores
DBCommitAll
Salva em disco todas as modificações.
Si n t a x e
172
DBCommitAll () ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função salva em disco todas as atualizações pendentes em todas as áreas de trabalho.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBCOMMITALL para salvar todas as
alterações realizadas nas áreas de trabalho abertas no momento.
USE Clientes NEW
DBGOTO(100)
Nome := "Jose"
USE Fornecedores NEW
DBGOTO(168)
Nome := "Joao"
DBCOMMITALL() // Salva em disco as alterações realizadas nas tabelas Clientes e
Fornecedores
DBCreate
Cria nova tabela.
Si n t a x e
aEstrutura S Array Lista com as informações dos campos para ser criada a tabela.
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função é utilizada para criar um novo arquivo de tabela cujo nome está especificado através do
primeiro parâmetro (cNo me) e estrutura através do segundo (aEst rut ura).
173
A estrutura é especificada através de um array com todos os campos, onde cada campo é expresso
através de um array contendo {Nome, Tipo, Tamanho, Decimais}, como visto no exemplo a seguir.
Ex e m p l o
// Este exemplo mostra como se pode criar novo arquivo de tabela através da função
DBCREATE:
LOCAL aEstrutura := {{Cod,N,3,0},{Nome,C,10,0},{Idade,N,3,0},{Nasc,D,8,0},{Pagto, N,7,2}}
DBCREATE("\teste\amigos.xxx",aEstrutura) // Cria a tabela com o RDD corrente
USE "\teste\amigos.xxx" VIA "DBFCDX" NEW
DBCreate I ndex
Cria um arquivo de índice.
Si n t a x e
Retorno
Descrição
D es c r i ç ã o
Esta função é utilizada para criar um novo arquivo de índice com o nome especificado através do primeiro
parâmetro, sendo que se o mesmo existir é deletado e criado o novo. Para tanto são executados os
passos a seguir:
174
Com exceção do RDD Ctree, a tabela corrente não precisa estar aberta em modo exclusivo para a criação
de índice, pois na criação de índices no Ctree é alterada a estrutura da tabela, precisando para isto a
tabela estar aberta em modo exclusivo.
Ex e m p l o
// Este exemplo mostra como se pode criar novo arquivo de índice criando a ordem sobre os
campos Nome e End e não aceitará duplicação:
USE Cliente VIA "DBFCDX" NEW
DBCREATEINDEX ("\teste\ind2.cdx","Nome+End",{ || Nome+End },.T.)
DBDelete
Marca o arquivo corrente como deletado.
Si n t a x e
DBDelete () ->Nil
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função marca o arquivo corrente como deletado de modo semelhante ao comando DELETE . Para
filtrar os arquivos marcados pode-se utilizar o comando SET DELETED e para deletá-los fisicamente pode-
se utilizar o comando PACK.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar a função DBDELETE() para marcar alguns
registros como deletados e o PACK para deletá-los fisicamente.
USE Clientes NEW
DBGOTO(100)
DBDELETE()
DBGOTO(105)
DBDELETE()
DBGOTO(110)
DBDELETE()
PACK
DBEval
Executa uma expressão para os registros dentro das condições especificadas.
175
Si n t a x e
D es c r i ç ã o
Esta função é utilizada para executar uma expressão definida pelo bloco de código do primeiro parâmetro
para cada registro que está dentro do escopo definido através dos blocos de condição de "for" e "while".
O número de registros a ser executado será definido com o parâmetro nProxRegs ou se setado o
parâmetro lRestan te serão executados todos os registros a partir do registro corrente até o final da tabela
corrente. Se for especificado o parâmetro nRecno apenas o registro com o recno especificado será
processado.
Se forem omitidos os blocos de "for" e "while", os mesmos serão considerados .T. como padrão, estão
assim todos os registros dentro do escopo.
Se o parâmetro lRestan te for omitido a tabela inicia o processamento dos registros a partir do topo da
tabela, caso contrário serão processados os registros a partir do posicionamento corrente da tabela.
Ex e m p l o
// Este exemplo mostra como se pode usar o DBEVAL para contar quantos registros estão
dentro do escopo especificado em toda a tabela, pois como o parâmetro lRestante foi
omitido a tabela irá para o topo antes de iniciar a processar os registros. Supondo que a
tabela está sobre um índice no campo idade, serão processados registros com o Nome cuja
ordem alfabética é maior que "FFFFF" e até encontrar algum registro de idade igual a 40:
USE Cliente VIA "DBFCDX" NEW
LOCAL nCount := 0;
DBGOTO(100)
DBEVAL( {|| nCount++}, {|| Nome > "FFFFF"}, {|| Idade < 40})
// Este exemplo mostra como se pode usar o DBEVAL para contar quantos registros estão
dentro do escopo especificado (como o exemplo anterior) a partir do registro atual (100):
USE Cliente VIA "DBFCDX" NEW
LOCAL nCount := 0;
176
DBGOTO(100)
DBEVAL( {|| nCount++}, {|| Nome > "FFFFF"}, {|| Idade < 40},,,.T.)
// Este exemplo mostra como se pode usar o DBEVAL para colocar numa variável um nome
inicial que está definido em um registro de recno definido (100):
USE Cliente VIA "DBFCDX" NEW
LOCAL cNomeIni := "";
DBEVAL( {|| cNomeIni := Nome},,,,100)
// Este exemplo mostra como se pode usar o DBEVAL para verificar qual é o recno do décimo
registro a partir do corrente dentro do escopo definido:
USE Cliente VIA "DBFCDX" NEW
LOCAL nRecno := 0;
DBGOTO(100)
DBEVAL( {|| nRecno := RECNO()}, {|| Nome > "FFFFF"}, {|| Idade < 40},10,,.T.)
DBF
Verifica qual é o Alias corrente.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Verifica qual é o Alias da área de trabalho corrente. O Alias é definido quando a tabela é aberta através do
parâmetro correspondente (DBUSEAREA()).
Esta função é o inverso da função SELECT(), pois nesta é retornado o número da área de trabalho do
Alias correspondente.
Ex e m p l o
// Este exemplo mostra como o DBF corrente pode ser mostrado para o usuário.
dbUseArea( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
MessageBox("O Alias corrente é: " + DBF(), "Alias", 0) // Resultado: "O Alias
corrente é: SSS"
DBField I nfo
Verifica informações sobre um campo.
177
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para obter informações sobre determinado campo da tabela corrente. O tipo
de informação (primeiro argumento) é escolhido de acordo com as constantes abaixo:
A posição do campo não leva em consideração os campos internos do Protheus (recno e deleted).
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBFIELDINFO para obter as informações
do primeiro campo da tabela Clientes.
USE Clientes NEW
DBFIELDINFO(DBS_NAME, 1) // Retorno: Nome
DBFIELDINFO(DBS_TYPE, 1) // Retorno: C
DBFIELDINFO(DBS_LEN, 1) // Retorno: 10
DBFIELDINFO(DBS_DEC, 1) // Retorno: 0
DBFil ter
Verifica a expressão de filtro corrente.
Si n t a x e
178
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para verificar a expressão de filtro ativo na área de trabalho corrente.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBFILTER para verificar a expressão do
filtro corrente.
USE Cliente INDEX Ind1 NEW
SET FILTER TO Nome > "Jose"
DBFILTER() // retorna: Nome > "Jose"
SET FILTER TO Num < 1000
DBFILTER() // retorna: Num < 1000
DBGoBo t tom
Posiciona no último registro lógico.
Si n t a x e
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função é utilizada para posicionar a tabela corrente no último registro lógico. A seqüência lógica
depende da ordem e do filtro ativo sobre a tabela corrente, portanto o último registro lógico pode não ser
o último registro físico.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBGOBOTTOM para posicionar no último
registro físico.
USE Cliente
DBGOBOTTOM() // Posiciona no último registro físico, pois não há ordem ativa
// Este exemplo demonstra como se pode utilizar o DBGOBOTTOM para posicionar no último
registro lógico.
USE Cliente INDEX Ind1 NEW
DBGOBOTTOM() // Posiciona no último registro lógico (último registro na seqüência gerada
pelo índice)
179
DBGoTo
Posiciona em determinado registro.
Si n t a x e
D es c r i ç ã o
Esta função é utilizada para posicionar a tabela corrente em determinado registro, segundo a ordem física
(seqüência sobre o recno).
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBGOTO para posicionar a tabela
corrente em determinado registro.
USE Cliente INDEX Ind1 NEW
DBGOTO(100) // Posiciona no registro de recno 100
DBGoTop
Posiciona no primeiro registro lógico.
Si n t a x e
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função é utilizada para posicionar a tabela corrente no primeiro registro lógico. A seqüência lógica
depende da ordem e do filtro ativo sobre a tabela corrente, portanto o primeiro registro lógico pode não
ser o primeiro registro físico.
Ex e m p l o
180
// Este exemplo demonstra como se pode utilizar o DBGOBOTOP para posicionar no primeiro
registro físico.
USE Cliente
DBGOTOP() // Posiciona no primeiro registro físico, pois não há ordem ativa
// Este exemplo demonstra como se pode utilizar o DBGOTOP para posicionar no primeiro
registro lógico.
USE Cliente INDEX Ind1 NEW
DBGOTOP() // Posiciona no primeiro registro lógico (primeiro registro na següência gerada
pelo índice)
DBI nfo
Verifica informações sobre a tabela corrente.
Si n t a x e
Tipo de informação a
nInfoTipo S N
ser verificada.
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para obter informações sobre a tabela corrente. O tipo de informação (primeiro
argumento) é escolhido de acordo com as constantes abaixo:
DBI_BOF Verifica se está posicionada no início da tabela similar a BOF (tipo lógico)
DBI_EOF Verifica se está posicionada no final da tabela similar a EOF (tipo lógico)
Verifica se a tabela está posicionada após uma pesquisa similar a FOUND (tipo
DBI_FOUND
lógico)
DBI_FCOUNT Número de campos na estrutura da tabela corrente similar a FCOUNT (tipo
181
numérico)
DBI_ALIAS Nome do Alias da área de trabalho corrente similar a ALIAS (tipo caracter)
DBI_LASTUPDATE Verifica a data da última modificação similar a LUPDATE (tipo data)
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBINFO para obter as informações da
tabela corrente (Clientes).
USE Clientes NEW
DBINFO(DBI_FULLPATH) // Retorno: C:\Teste\Clientes.dbf
DBINFO(DBI_FCOUNT) // Retorno: 12
DBGOTOP()
DBINFO(DBI_BOF) // Retorno: .F.
DBSKIP(-1)
DBINFO(DBI_BOF) // Retorno: .T.
DBOrder I nfo
Verifica informações sobre uma ordem.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para obter informações sobre determinada ordem. A especificação da ordem pode
ser realizada através de seu nome ou sua posição dentro da lista de ordens, mas se ela não for
especificada serão obtidas informações da ordem corrente.
182
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBORDERINFO para obter informações
sobre o nome do arquivo de índice da ordem corrente.
DBORDERINFO(DBOI_BAGNAME) // retorna: Ind
DBORDERINFO(DBOI_FULLPATH) // retorna: C:\AP6\Teste\Ind.cdx
// Este exemplo demonstra como se pode utilizar o DBORDERINFO para obter informações
sobre o nome do arquivo de índice de uma ordem especificada.
DBORDERINFO(DBOI_BAGNAME,,3) // retorna: Ind2
DBORDERINFO(DBOI_FULLPATH,,"Nome") // retorna: C:\AP6\Teste\Ind2.cdx
// Este exemplo demonstra como se pode utilizar o DBORDERINFO para obter o número de
ordens de determinado arquivo de índice.
DBORDERINFO(DBOI_ ORDERCOUNT,"\Teste\Ind2.cdx") // retorna: 3
DBOrderNickName
Torna ativa a ordem com o determinado apelido.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para selecionar a ordem ativa através de seu apelido. Esta ordem é a responsável
seqüência lógica dos registros da tabela corrente.
Ex e m p l o
//Este exemplo demonstra como se pode utilizar o DBORDERNICKNAME para setar nova ordem.
USE Cliente NEW
SET INDEX TO Nome, Idade
183
IF !DBORDERNICKNAME("IndNome")
Messagebox("Registro não encontrado","Erro", 0)
BREAK
ENDIF
DBRecall
Altera o estado deletado do registro atual.
Si n t a x e
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Esta função é utilizada para retirar a marca de registro deletado do registro atual. Para ser executada o
registro atual deve estar bloqueado ou a tabela deve estar aberta em modo exclusivo. Se o registro atual
não estiver deletado, esta função não faz nada. Ela é o oposto da função DBDELETE que marca o registro
atual como deletado.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBRECALL para retornar o estado do
registro atual para normal.
USE Cliente
DBGOTO(100)
DBDELETE()
DELETED() // Retorna: .T.
DBRECALL()
DELETED() // Retorna: .F.
// Este exemplo demonstra como se pode utilizar o DBRECALL para desfazer todas as
deleções da tabela corrente.
USE Cliente
DBGOTOP()
WHILE !EOF()
DBRECALL()
DBSKIP()
ENDDO
DBRecord I nfo
Verifica informações sobre um registro.
Si n t a x e
184
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para obter informações sobre o registro especificado pelo segundo argumento
(recno) da tabela corrente, se esta informação for omitida será verificado o registro corrente. O tipo de
informação (primeiro argumento) é escolhido de acordo com as constantes abaixo:
Verifica se o registro foi alterado e ainda não foi atualizado fisicamente. Similar a
DBRI_UPDATED
UPDATED (tipo lógico).
Ex e m p l o
DBReindex
Reconstrói todos os índices da área de trabalho.
Si n t a x e
185
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Reconstrói todos os índices da área de trabalho corrente e posiciona as tabelas no primeiro registro lógico.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBREINDEX para reconstruir os índices
depois que um novo índice foi gerado.
USE Clientes NEW
DBSETINDEX("IndNome")
DBREINDEX()
DBRLock
Bloqueia determinado registro.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada quando se tem uma tabela aberta e compartilhada e se deseja bloquear um
registro para que outros usuários não possam alterá-lo. Se a tabela já está aberta em modo exclusivo, a
função não altera seu estado.
O usuário pode escolher o registro a ser bloqueado através do parâmetro (recno), mas se este for omitido
será bloqueado o registro corrente como na função RLOCK().
186
Ex e m p l o
DBRLockList
Retorna uma lista com todos os registros locados na tabela corrente.
Si n t a x e
Retorno Descrição
Nil Não existe tabela cor ren te ou não existe nenhum regist ro locado.
D es c r i ç ã o
Esta função é utilizada para verificar quais registros estão locados na tabela corrente. Para tanto, é
retornada uma tabela unidimensional com os números dos registros.
Ex e m p l o
// Este exemplo mostra como é utilizada a função DBRLOCKLIST para verificar quais
registros estão bloqueados na tabela corrente
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBGOTOP()
DBRLOCK() // Bloqueia o primeiro registro
DBRLOCK(110) // Bloqueia o registro de número 110
DBRLOCK(100) // Bloqueia o registro de número 100
DBRLOCKLIST() // Retorna: {1,100,110}
DBRunLock
Desbloqueia determinado registro.
Si n t a x e
187
Retorno Descrição
D es c r i ç ã o
O usuário pode escolher o registro a ser desbloqueado através do parâmetro (recno), mas se este for
omitido será desbloqueado o registro corrente como na função DBUNLOCK().
Ex e m p l o
DbSeek
Encontra um registro com determinado valor da chave do índice.
Si n t a x e
188
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para encontrar um registro com determinado valor da expressão de chave de
índice.
Antes da chamada do DBSEEK deve-se certificar de que existe uma ordem ativa no momento com os
campos que se deseja pesquisar o valor.
Se a expressão possuir apenas uma campo numérico, o primeiro parâmetro deve ser do tipo numérico,
mas nos demais casos deve-se utilizar um valor do tipo caracter para este parâmetro (mesmo se forem
apenas dois campos numéricos ou do tipo data).
Quando o segundo parâmetro for especificado como .T. (softseek), mesmo que a expressão pesquisada
não encontrar nenhum registro com este valor, a tabela será posicionada no próximo valor maior que o
especificado no primeiro parâmetro, mas mesmo posicionando no próximo valor esta função retornará .F.
(pois não encontrou).
Quando não for especificado este valor ou estiver .F. e falhar o valor de pesquisa, a tabela será
posicionada em LASTREC + 1 e será setada a flag de EOF.
Se o terceiro parâmetro for especificado com valor .T. a função posiciona a tabela no último registro com
o valor procurado, caso não seja especificado ou for .F., será posicionada na primeira ocorrência.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSEEK para busca de valores numéricos.
USE Clientes NEW
ORDLISTADD ("/teste/ind1.cdx") // Expressão é Num (campo numérico)
DBSEEK(100) // Retorna: .F.
EOF() // Retorna: .T.
DBSEEK(100,.T.) // Retorna: .F.
EOF() // Retorna: .F. (pois o softseek posicionou no próximo registro)
// Este exemplo demonstra como se pode utilizar o DBSEEK para percorrer todos os
registros de Clientes com o nome joao e vencimentos a partir de janeiro de 2001.
USE Clientes NEW
ORDLISTADD ("/teste/ind2.cdx") // Expressão é Nome+Venc (campo caracter + data)
DBSEEK("joao200101",.T.) // Procura a primeira ocorrência de Nome "joao" e vencimento
maior que Janeiro de 2001
189
DBSetDriver
Modifica ou verifica o RDD padrão.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função pode ser utilizada apenas para verificar qual o RDD que está definido como padrão quando for
omitido seu parâmetro.
Ela também pode ser utilizada para especificar outro RDD como padrão, especificando-o através do
parâmetro.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSETDRIVER para alterar o valor do RDD
padrão.
DBSETDRIVER("CTREECDX") // Retorna: DBFCDX
DBSETDRIVER() // Retorna: CTREECDX
DBSetFil ter
Seta uma condição de filtro.
Si n t a x e
190
Retorno 3Descrição
D es c r i ç ã o
Esta função é utilizada para setar um filtro nos registros da tabela corrente especificado através do bloco
de código no primeiro parâmetro.
Quando um registro não está dentro do filtro setado ele continua existindo fisicamente, mas não
logicamente (nas funções de manipulação de banco de dados como DBGOTOP, DBSEEK , DBSKIP, etc).
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSETFILTER para filtrar todos os
clientes com menos de 40 anos.
USE Cliente NEW
DBSETFILTER( {|| Idade < 40}, "Idade < 40" )
DBGOTOP()
DBSet I ndex
Acrescenta todas as ordens de determinado índice à lista.
Si n t a x e
cArq Indice Sim C Nome do arquivo de índice, com ou sem diretório e extensão.
Retorno Descrição
191
D es c r i ç ã o
Esta função é utilizada para acrescentar uma ou mais ordens de determinado índice na lista de ordens
ativas da área de trabalho.
Quando o arquivo de índice possui apenas uma ordem, a mesma é acrescentada à lista e torna-se ativa.
Quando o índice possui mais de uma ordem, todas são acrescentadas à lista e a primeira torna-se ativa.
Para se utilizar arquivos de extensão padrão do RDD, este dado pode ser omitido no primeiro parâmetro,
mas caso contrário deve ser especificado.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSETINDEX para acrescentar novos
índices à lista de ordens.
USE Cliente NEW
DBSETINDEX("Ind1")
DBSETINDEX("\teste\Ind2.cdx")
DBSet NickName
Seta um apelido para determinada ordem ou verifica qual é o apelido corrente.
Si n t a x e
Retorno Descrição
"" Não conseguiu encontrar a ordem especificada, não conseguiu setar o apelido ou não havia
apelido corrente
192
D es c r i ç ã o
Esta função é utilizada para colocar um apelido em determinada ordem especificada pelo primeiro
parâmetro.
Caso seja omitido o nome do apelido a ser dado, a função apenas verifica o apelido corrente.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSETNICKNAME para setar um novo
apelido e verificar qual o apelido atual.
USE Cliente NEW
DBSETNICKNAME("IndNome") // retorna: ""
DBSETNICKNAME("IndNome","NOME") // retorna: ""
DBSETNICKNAME("IndNome") // retorna: "NOME"
DBSetOrder
Seleciona a ordem ativa da área de trabalho.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSETORDER para selecionar a ordem
corrente.
193
DBSkip
Desloca para outro registro na tabela corrente.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para deslocar para outro registro a partir do registro atual.
O parâmetro especifica quantos registros lógicos devem ser deslocados a partir do corrente, se for positivo
desloca em direção ao final da tabela, se for negativo ao início da tabela e caso seja omitido irá para o
próximo registro (o padrão é 1).
Caso passe do início da tabela, posiciona no primeiro registro e seta BOF, caso passe do final da tabela,
posiciona no registro LASTREC + 1 e seta EOF.
Ex e m p l o
// Este exemplo mostra como o DBSKIP pode passar do final da tabela e do início da tabela
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBGOBOTTOM()
EOF() // retorna .F.
DBSKIP()
EOF() // retorna .T.
DBGOTOP()
BOF() // retorna .F.
DBSKIP(-1)
BOF() // retorna .T.
// Este exemplo mostra como o DBSKIP pode deslocar 10 registro em relação ao registro
corrente
DBUSEAREA(.T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBGOTO(100)
DBSKIP(10)
RECNO() // retorna 110
194
DBSKIP(-10)
RECNO() // retorna 100
DBSt ruct
Retorna a estrutura da tabela corrente.
Si n t a x e
Retorno Descrição
aEstrutura Array com todos os campos, onde cada elemento é um subarray contendo Nome,
Tipo, Tamanho e Decimais.
D es c r i ç ã o
Esta função é utilizada para verificar a estrutura da tabela corrente da mesma forma que é utilizada para
criar a tabela com a função DBCREATE.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBSTRUCT para recuperar a estrutura da
tabela corrente.
USE Cliente NEW
DBSTRUCT()
//Retorna:{{Cod,N,3,0},{Nome,C,10,0},{Idade,N,3,0},{Nasc,D,8,0},{Pagto,N,7,2}}
DBUnlock
Desbloqueia todos os registros da tabela corrente.
Si n t a x e
Retorno Descrição
195
NIL Se m retorno.
D es c r i ç ã o
Esta função é utilizada para liberar todos os registros bloqueados e é equivalente a executar DBRUNLOCK
para todos os registros da lista DBRLOCKLIST.
Ex e m p l o
// Este exemplo mostra como liberar todos os registros bloqueados da tabela corrente.
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBUNLOCK()
DBUnlockAll
Desbloqueia todos os registros de todas as tabelas abertas.
Si n t a x e
Retorno Descrição
NIL Se m re torno.
D es c r i ç ã o
Esta função é utilizada para liberar todos os registros bloqueados e é equivalente a executar DBUNLOCK
para todos os registros da lista DBRLOCKLIST de todas as áreas de trabalho.
Ex e m p l o
// Este exemplo mostra como liberar todos os registros bloqueados da tabela corrente.
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBUNLOCKALL()
Delete
Marca registros como deletados.
Si n t a x e
DELETE [FOR CondFor] [WHILE CondWhile] [NEXT nRecs] [RECORD nRecno] [REST] [ALL]
196
nRecno Não N
Número do recno do registro a ser deletado.
Retorno Descrição
D es c r i ç ã o
Este comando é utilizado para marcar alguns registros da tabela corrente como deletados.
Se não forem especificadas as condições para que o registro seja marcado como deletado, marca toda a
tabela como se estivesse especificada a opção "ALL".
Pode-se especificar um escopo para que os registros sejam marcados através das opções "FOR CondFor" e
"WHILE CondWhile".
Pode-se também limitar o número de registros a serem marcados através da opção "NEXT nRecs" e
determinar que a "deleção" dos registros deve-se iniciar a partir do registro atual com "REST", mas caso
contrário o comando executa um DBGOTOP() antes de iniciar a "deleção".
Se é desejado marcar apenas determinado registro pode-se defini-lo através da especificação do recno
com "RECORD nRecno".
Ex e m p l o
// Este exemplo demonstra como utilizar o comando DELETE para marcar alguns registros
dentro de determinado escopo como deletado. Este escopo é definido por Idade > 20, até
que o nome seja maior ou igual a "VVV", começa a deleção a partir do registro atual e
marca apenas 10 registros:
USE Cliente VIA "CTREECDX" NEW
DELETE FOR Idade>20 WHILE Nome<"VVV" NEXT 10 REST
197
Deleted
Verifica se o registro foi deletado.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Quando o registro é deletado, permanece fisicamente na tabela, mas fica marcado como "deletado". Esta
função verifica este estado. Quando é executada a função DBPACK todos os registros marcados como
deletados são apagados fisicamente enquanto a função DBRECALL marca todos os registros deletados
como não-deletados.
Ex e m p l o
// Este exemplo verifica se determinado registro está deletado, caso positivo, mostra uma mensagem:
DevOu tPict
Imprime o conteúdo na posição corrente formatando a saída.
Si n t a x e
198
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
Ex e m p l o
nVal:= 100.89
DevPos( 10,10 ) // configura linha 0, coluna 0 para impressão
//@ Prow(),Pcol() PSAY "Minha linha e "+str( Prow() )
DevOutPict( nVal, "@E 999,999.99" ) // imprime 100,89
DevPos
Posiciona linha e coluna de impressão.
Si n t a x e
Retorno Descrição
NIL Nenhum
D es c r i ç ã o
DEVPOS( ) modifica a linha e coluna corrente de impressão. Modifica os retornos de PROW() e PCOL( ).
Ex e m p l o
199
Directory
Cria um array com dados dos diretórios e dos arquivos.
Si n t a x e
Atributo Descrição
cAtributos Não C
H Incluir arquivos ocultos (Hidden)
Incluir diretórios
D
Retorno Descrição
D es c r i ç ã o
200
DIRECTORY() é função que retorna informações de arquivos/diretórios que correspondam a uma máscara
especifica.
Tanto arquivos no servidor como no cliente (Remote) são aceitos. Os atributos são sempre aditivos.
Ex e m p l o s
#include "Directry.ch"
//
aDirectory := DIRECTORY("*.*", "D")
AEVAL( aDirectory, {|aFile| QOUT(aFile[F_NAME])} )
DirRemove
Elimina um diretório.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Note que é necessário ter direitos suficientes para remover um diretório, e o diretório para ser eliminado
precisa estar vazio, sem subdiretórios e arquivos.
Ex e m p l o
201
DiskSpace
Retorna o espaço disponível em um disco específico.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
DISKSPACE() é uma função de ambiente que determina quantos bytes estão disponíveis em um
determinado disco.
Ao ser utilizado zero e o diretório corrente for local, será retornado o espaço disponível no cliente ( remote
), caso o diretório corrente esteja no servidor, será retornado o espaço disponível no servidor.
Ex e m p l o s
Do w
Converte uma data para o valor numérico do dia da semana.
Si n t a x e
202
Retorno Descrição
D es c r i ç ã o
DOW() é uma função que converte uma data para o valor numérico que representa o dia da semana. Útil
quando se deseja fazer cálculos semanais. DOW() é similar a CDOW(), que retorna o dia da semana como
uma cadeia de caracteres.
Ex e m p l o s
Estes exemplos mostram como usar CDOW() e o seu relacionamento com DOW():
Esta função de usuário utiliza DOW() para calcular a data da última segunda-feira da data informada.
FUNCTION LastMonday(dData)
RETURN (dData - DOW(dData) + 2)
Dt oc
Converte uma data para cadeia de caracteres.
Si n t a x e
203
Retorno Descrição
D es c r i ç ã o
DTOC() converte uma data para uma cadeia de caracteres formatada segundo o padrão corrente, definido
pelo comando SET DATE. Se for necessária a utilização de formatação especial, use a função
TRANSFORM() <a>.
Em expressões de índices de arquivo, use DTOS() no lugar de DTOC() para converter datas para cadeia de
caracteres.
Ex e m p l o s
Dt os
Converte uma data para uma cadeia de caracteres no formato yyyymmdd.
Si n t a x e
Retorno Descrição
Caracter Retorna uma cadeia de caracteres com oito byte de tamanho no formato yyyymmdd. Quando
dDa ta é nulo ou invalido, DTOS() retorna uma cadeia de caracteres com oito espaços. O
valor retornado não é afetado pela formato da data corrente.
D es c r i ç ã o
DTOS() é uma função de conversão de data que pode ser usada para criar expressões de índice. O
resultado é estruturado visando manter a ordem correta do índice (ano, mês, dia).
204
Ex e m p l o s
Eject
Força a impressão de nova página no relatório.
Si n t a x e
Retorno Descrição
NIL Se m re torno
D es c r i ç ã o
Ex e m p l o
ElapTime
Retorna o tempo decorrido entre duas horas.
Si n t a x e
205
Retorno Descrição
D es c r i ç ã o
ElapTime() retorna uma cadeia de caracteres contendo a diferença de tempo no formato hh:mm:ss, onde
hh é a hora ( 1 a 24 ), mm os minutos e ss os segundos.
Ex e m p l o s
FClose
Fecha um arquivo binário e grava os buffers no disco.
Si n t a x e
Retorno Descrição
206
D es c r i ç ã o
Fecha um manipulador ( handle ) de um arquivo binário. Este manipulador deve ter sido aberto através
das funções FOPEN(), FOPENPORT(), FCREATE().
Ex e m p l o
#include "Fileio.ch"
//
nHandle := FCREATE("Testfile", FC_NORMAL)
IF !FCLOSE(nHandle)
conout ("Erro fechando arquivo:" + Str(FError( 0 )
ENDIF
FCreate
Cria um arquivo, ou elimina o conteúdo de um arquivo.
Si n t a x e
Nome do arquivo a ser criado, o caminho pode ser incluído. São válidos
cArq S C
caminhos no local (remote) e no servidor.
Retorno Descrição
>0 Numérico. O Handle do arquivo para ser usado nas demais funções de arquivo.
-1
Erro na criação do arquivo, verifique FERROR() para obter maiores detalhes do erro.
D es c r i ç ã o
FCREATE() é uma função de baixo-nível que permite a manipulação direta dos arquivos textos como
binários.
207
Ao ser executada FCREATE() cria um arquivo ou elimina o seu conteúdo, e retorna o handle (Manipulador)
do arquivo, para ser usado nas demais funções.
Os Atributos para criação do arquivo estão abaixo, e estão definidos no header fileio.ch.
Note que se o arquivo existir, o conteúdo será truncado para zero bytes.
Ex e m p l o
#include "Fileio.ch"
IF (nHandle := FCREATE("Testfile", FC_NORMAL)) == -1
? "Arquivo não pode ser criado", FERROR()
BREAK
ELSE
FWRITE(nHandle, "ola!!!")
FCLOSE(nHandle)
ENDIF
FErase
Apaga um arquivo do disco.
Si n t a x e
208
Retorno Descrição
-1 O Arquivo não foi apagado, verifique FERROR() para obter maiores detalhes.
D es c r i ç ã o
O Arquivo para ser apagado deve estar fechado. Não é permitido a utilização de caracteres coringa
(wildcards).
Ex e m p l o s
FError
Verifica se houve erros após uma operação com arquivos binários.
Si n t a x e
Retorno Descrição
5 Acessso negado
8 Memória Insuficiente
209
30 Erro de leitura
32 Violação de compartilhamento
33 Erro de Lock
D es c r i ç ã o
FERROR() é a função que retorna o código de erro mais específico, após a execução de funções com
arquivos binários, tais como: FOPEN(), FCLOSE(), FWRITE(), FREAD().
Ex e m p l o
#include "Fileio.ch"
//
nHandle := FCREATE("Temp.txt", FC_NORMAL)
IF FERROR() != 0
conout ("Erro ao criar o arquivo, Erro:" Str(FError())
ENDIF
FieldBlock
Retorna um bloco de código para um campo determinado da tabela corrente.
Si n t a x e
Retorno Descrição
210
bBloco Bloco de código. Bloco de código para o campo especificado na tabela corrente.
D es c r i ç ã o
Esta função é utilizada para retornar um bloco de código executável com o campo especificado. Sendo que
quando o bloco resultante é executado sem valor recupera o valor armazenado no campo, mas quando
executado com um valor, seta este valor no determinado campo.
Ex e m p l o
// Este exemplo mostra como se pode usar o FIELDBLOCK para criar o bloco de código para o
campo Nome da tabela corrente na variável bBloco:
USE Cliente VIA "DBFCDX" NEW
bBloco := FIELDBLOCK("Nome")
FieldWbl
Retorna um bloco de código para um campo determinado especificando a área de trabalho.
Si n t a x e
FIELDWBLOCK( < cCa mpo > , < nArea > ) --> Bloco de Código
Retorno Descrição
bWBloco Bloco de código. Bloco de código para o campo especificado na área de trabalho determinada.
D es c r i ç ã o
Esta função é utilizada para retornar um bloco de código executável com o campo especificado em
determinada área de trabalho. Sendo que quando o bloco resultante é executado sem valor recupera o
valor armazenado no campo, mas quando executado com um valor seta esta valor no determinado
campo.
211
Ex e m p l o
// Este exemplo mostra como se pode usar o FIELDWBLOCK para criar o bloco de código para
o campo Nome da área de trabalho 3 na variável bBloco:
USE Cliente VIA "DBFCDX" NEW
bBloco := FIELDBLOCK("Nome",3)
File
Verifica se um arquivo ou máscara de arquivos existem.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Ex e m p l o s
212
FOpen
Abre um arquivo binário.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
FOPEN() abre um arquivo de modo binário, permitindo a leitura ou gravação atráves das funções
FREAD(), FWRITE().
Todo arquivo aberto através da FOPEN(), deve ser fechado através da FCLOSE().
O modo de abertura é composto de modo de acesso e modo de compartilhamento, esses modos estão
descritos em fileio.ch.
Modos de Acesso
213
Modos de Compartilhamento
FO_EXCLUSIVE Exclusivo
Serão aceitos tantos caminhos baseados no servidor, como caminhos locais ( remote ).
Ex e m p l o
Este exemplo usa o FOPEN() para abrir um arquivo para leitura/gravação de maneira compartilhada e
mostra uma mensagem de erro caso a abertura falhe:
#include "Fileio.ch"
//
nHandle := FOPEN("Temp.txt", FO_READWRITE + FO_SHARED)
IF FERROR() != 0
? "Impossivel abrir o arquivo, Erro : ", FERROR()
BREAK
ENDIF
FOpenPor t
Abre uma porta paralela ou serial.
Si n t a x e
214
Retorno Descrição
D es c r i ç ã o
FOPENPORT() abre um dispositivo, permitindo a leitura ou gravação atráves das funções FREAD(),
FWRITE().
Todo arquivo aberto através da FOPENPORT(), deve ser fechado através da função FCLOSE().
O modo de abertura é composto de modo de acesso e modo de compartilhamento, esses modos estão
descritos em fileio.ch.
Modos de Acesso
Modos de Compartilhamento
FO_EXCLUSIVE Exclusivo
215
O dispositivo será aberto no diretório corrente, ou seja, caso o diretório esteja posicionado no cliente, o
dispositivo será aberto no cliente ( Remote ), caso contrário será aberto no servidor.
Os parâmetros das portas seriais servem para configurar a comunicação serial e podem ser os seguintes:
Ex e m p l o
Este exemplo usa o FOPENPORT() para abrir uma porta de impressão para gravação e mostra uma
mensagem de erro caso a abertura falhe:
#include "Fileio.ch"
//
nHandle := FOPENPORT("LPT1:", "", FO_WRITE)
IF FERROR() != 0
? "Impossivel abrir a impressora LPT1, Erro : ", FERROR()
BREAK
ENDIF
Este exemplo abre uma porta serial e espera para obter uma leitura da porta.
#include "Fileio.ch"
//
CURDIR( "C:\TEMP" ) // Posicionando no diretório cliente ( Remote )
nHandle := FOPENPORT("COM1:", "9600,N,8,1,10000", FO_WRITE)
IF FERROR() != 0
? "Impossivel abrir a impressora LPT1, Erro : ", FERROR()
BREAK
ENDIF
FREAD(
FRead
Lê caracteres binários de um arquivo.
Si n t a x e
216
FOPENPORT()
Retorno Descrição
D es c r i ç ã o
FREAD() lerá até o número de bytes informado em nQt dBy tes; caso aconteça algum erro ou o arquivo
chegue ao final, FREAD() retornará um número menor que o nQt dBy tes.
O buffer passado para leitura deve ser sempre pré-alocado e passado como referência. Caso contrário, os
dados não poderão ser retornados.
FREAD() lê a partir da posição atual do ponteiro, que pode ser ajustado pelo FSEEK() ou por FWRITE(),
FREADSTR().
Ex e m p l o s
FReadSt r
217
Si n t a x e
Retorno Descrição
D es c r i ç ã o
FREAD() lerá até o número de bytes informado em nQt dBy tes ou até encontrar um CHR(0). Caso aconteça
algum erro ou o arquivo chegue ao final, FREAD() retornará uma string menor do que nQdBy tes e
colocará o erro em FERROR().
FREADSTR() lê a partir da posição atual do ponteiro, que pode ser ajustado pelo FSEEK() ou por FWRITE(
), FREAD().
Ex e m p l o s
#include "Fileio.ch"
//
nHandle := FOPEN("New.txt", FC_NORMAL)
IF FERROR() != 0
? "Erro abrindo o arquivo", FERROR()
ELSE
cString := FREADSTR(nHandle, 16)
? cString
FCLOSE(nHandle)
ENDIF
Frename
Muda o nome de um arquivo.
218
Si n t a x e
Retorno Descrição
D es c r i ç ã o
FRENAME() renomeia um arquivo para outro nome, tanto no servidor como na estação. Ao renomear um
arquivo não esqueça que esta arquivo deverá estar fechado.
Ex e m p l o s
FSeek
Posiciona o arquivo binário.
Si n t a x e
nOffset Sim N Número de bytes que o ponteiro do arquivo deve ser movido a partir
da origem informada em nOrigem. O número pode ser positivo ou
219
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
FWrite
Grava em um arquivo binário.
Si n t a x e
220
Retorno Descrição
Numérico Quantidade de bytes efetivamente gravados. Se o retorno for menor que o nQtdBy tes,
houve um erro na gravação. Verifique FERROR() para mais detalhes.
D es c r i ç ã o
FWRITE() gravará até o número de bytes informado em nQt dBy tes; caso aconteça algum erro, retornará
um número menor que o nQt dBy tes.
FWRITE() grava a partir da posição atual do ponteiro, que pode ser ajustado pelo FSEEK() ou por
FREAD(), FREADSTR().
Ex e m p l o s
#include "Fileio.ch"
#define F_BLOCK 512
//
cBuffer := SPACE(F_BLOCK)
nInfile := FOPEN("Temp.txt", FO_READ)
nOutfile := FCREATE("Newfile.txt", FC_NORMAL)
lDone := .F.
//
DO WHILE !lDone
nBytesRead := FREAD(nInfile, @cBuffer, F_BLOCK)
IF FWRITE(nOutfile, cBuffer, nBytesRead) < ;
nBytesRead
? "Erro gravando: ", FERROR()
lDone := .T.
ELSE
lDone := (nBytesRead == 0)
ENDIF
ENDDO
//
FCLOSE(nInfile)
FCLOSE(nOutfile)
221
Get I mpWindo ws
Retorna lista de impressoras disponíveis para impressão.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
Si n t a x e
Retorno Descrição
222
D es c r i ç ã o
Ex e m p l o
GetClien tDir
Retorna o diretório onde está instalado o Remote.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
Header
Verifica o tamanho do cabeçalho da tabela corrente.
Si n t a x e
Retorno Descrição
223
D es c r i ç ã o
Esta função pode ser utilizada em conjunto com as funções RecSize e RecCount para calcular o tamanho
ocupado no disco pela tabela corrente. Pois, o tamanho será Header+RecSize*RecCount.
Ex e m p l o
// Este exemplo calcula o tamanho ocupado pela tabela "AA1990.DBF" no disco (número de
bytes):
USE "\DADOSADV\AA1990.DBF" SHARED NEW
nCabecalho := HEADER()
nDados := RecSize() * RecCount()
nTamanhoTotal := nCabecalho + nDados
I ndexKey
Verifica qual a expressão de chave de um índice.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para verificar qual é a expressão de chave de determinado índice, especificado pela
posição do índice na lista pelo primeiro parâmetro.
Se for passado parâmetro igual a 0, será retornada a expressão de chave do índice atual.
Ex e m p l o
// Este exemplo mostra como o INDEXKEY() pode recuperar a expressão do índice atual:
224
I ndexOrd
Verifica a posição do índice corrente.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função retorna a posição ocupada pelo índice corrente dentro da lista de índices.
Ex e m p l o
I nitPrin t
Inicializa parâmetros de impressão de relatório.
Si n t a x e
INITPRINT([ nOutPu t ], [ cNa meRel ], [ cTy pe ] ,[ lPor t ],[ cPat hAtu ]) --> NIL
cType Não C Tipo do relatório. "220" = 220 colunas, "132L"= 132 colunas
landscape (Padrão), "132P"= 132 colunas portrait, "080" = 80
225
colunas portrait
Retorno Descrição
D es c r i ç ã o
INITPRINT() inicializa parâmetros de impressão de relatório. Define onde será a saída de impressão e qual
vai ser a formatação de saída.
Ex e m p l o
/* Inicializa relatório para imprimir via Client "Meu relatório" em formulário de 132
colunas
em Landscape */
InitPrint( 1,"Meu relatório", "132L" )
I sPrin ter
Verifica se impressora está disponível.
Si n t a x e
Retorno Descrição
226
D es c r i ç ã o
ISPRINTER( ) testa a disponibilidade de impressoras conectadas fisicamente à máquina onde está sendo
executado o Server ou Remote Protheus. Dependendo do sistema operacional, o teste pode ser um
Assembler em Windows 95 ou 98, ou a criação de um arquivo em Windows NT,2000 e Unix.
Nos casos onde o teste é efetuado por criação de arquivo, o nErrorCode não será informado.
Ex e m p l o
I sCisaSyncOn
Verifica se o uso do CisaSync está habilitado.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para verificar se o uso do CisaSync está habilitado ou não.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar IsCisaSyncOn verificar se o CisaSync está
habilitado.
USE Cliente NEW
IF (ISCISASYNCON())
QOUT("CisaSync habilitado")
ELSE
QOUT("CisaSync desabilitado")
ENDIF
Locate
Pesquisa um registro segundo um determinado escopo.
Si n t a x e
227
LOCATE FOR CondFor [WHILE CondWhile] [NEXT nRecs] [RECORD nRecno] [REST] [ALL]
D es c r i ç ã o
Este comando é utilizado para encontrar um registro com determinado valor dentro de um escopo
especificado na tabela corrente.
Se a pesquisa obteve êxito, a flag FOUND retorna .T. e a tabela é posicionada no registro encontrado;
caso FOUND retorne .F., a tabela é posicionada em EOF.
Se as opções do escopo forem omitidas (CondWhile, nRecs e nRecno), todos os registros são pesquisados,
desde o primeiro como a opção "ALL".
Caso contrário, a opção "WHILE CondWhile" determina quando a busca deve parar (a expressão retornar
.F.); "NEXT nRecs" determina quantos registros devem ser pesquisados na busca; "RECORD nRecno"
determina o recno do registro a ser verificado na busca; "REST" significa que a busca deve começar a
partir do próximo registro.
Ex e m p l o
// Este exemplo demonstra como utilizar o comando LOCATE no seu modo mais usual:
USE Cliente NEW
LOCATE FOR Nome="Jose"
FOUND() // Retorna: .T.
EOF() // Retorna: .F.
RECNO() // Retorna: 5
LOCATE FOR Nome="DDDDD"
FOUND() // Retorna: .F.
EOF() // Retorna: .T.
RECNO() // Retorna: 85
// Este exemplo demonstra como se pode utilizar o comando LOCATE para lista todos os
Cliente de nome "Jose" com idade 20 anos:
USE Cliente NEW
DBGOTOP()
LOCATE FOR Idade=20 WHILE Nome="Jose"
DO WHILE FOUND()
DBSKIP()
LOCATE REST FOR Idade=20 WHILE Nome="Jose"
ENDDO
228
LUpdate
Verifica a data da última modificação da tabela corrente.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função verifica qual a data da última modificação e fechamento da tabela corrente, caso não exista
tabela corrente é retornada uma data em branco.
Ex e m p l o
// Mostra a data da última modificação da tabela corrente, caso não exista tabela
corrente mostra uma mensagem de erro:
dModificacao := LUpdate()
IF (EMPTY(dModificacao))
Messagebox("Não há tabela corrente","Erro", 0)
BREAK
ELSE
CONOUT ("A data da ultima modificacao e: " + DTOS(dModificacao))
ENDIF
MakeDir
Cria um diretório.
Si n t a x e
Retorno Descrição
229
D es c r i ç ã o
Ex e m p l o
MemoLine
Extrai uma linha de uma string ou de um campo memo.
Si n t a x e
MEMOLINE( cSt ring, [ nLineLengt h ], [ nLineNu mber ], [ nTabSize ], [ lWrap ]) --> Caracter
nLineLength Não N Número de caracteres por linha. Caso não especificado, assume 79.
nLineNumber Não N Número da linha a ser retornada. Caso não especificado, assume 1.
nTabSize Não N Define o número de caracteres para o Tab. Caso não especificado,
assume 4.
lWrap Não L Habilita a quebra de linhas de acordo com as palavras. Caso não
especificada, fica habilitado.
Retorno Descrição
Caracter Caracter. Retorna a linha solicitada, caso não exista o número de linhas, retorna uma string
em branco.
D es c r i ç ã o
MemoLine() é uma função que retorna uma linha específica. Caso não exista a linha especificada, retorna
um string em branco.
230
Caso a quebra de linhas esteja habilitada (lWrap igual .T.) e a palavra esteja no meio da quebra de linha,
esta será colocada na próxima linha.
MemoLine() é usada em conjunto com MLCOUNT() para extrair todas as linhas de um texto.
Ex e m p l o s
MemoRead
Lê um arquivo texto e retorna uma string.
Si n t a x e
cFile Sim C Nome do arquivo texto que deverá ser lido. Caminhos podem ser
incluídos.
Retorno Descrição
variável Caracter. MEMOREAD() retorna uma string com no máximo 65.535 bytes do arquivo
informado.
D es c r i ç ã o
MemoRead() lê um arquivo texto e armazena o conteúdo em uma variável string. O arquivo pode conter
no máximo 65.535 bytes.
Caso o arquivo não possa ser aberto, MemoRead retornará uma string vazia ( "" ).
Ex e m p l o s
cString = MEMOREAD("Temp.txt")
if empty( cString )
231
MemoWrite
Grava uma string para um arquivo em disco.
Si n t a x e
Retorno Descrição
.F. Houve falha na criação e gravação do arquivo, verifique FERROR() para obter detalhes o erro.
D es c r i ç ã o
MEMOWRITE() é uma função que grava o conteúdo de uma string em um arquivo em disco.
Ex e m p l o s
MLCoun t
Conta o número de linhas de uma String.
Si n t a x e
232
nLineLength Não N Número de caracteres por linha. Caso não especificado, assume 79.
nTabSize Não N Define o número de caracteres para o Tab. Caso não especificado,
assume 4.
Retorno Descrição
D es c r i ç ã o
MLCOUNT() retorna o número de linhas de uma string baseado nos parâmetros informados.
Ex e m p l o s
Mon t h
Converte o valor da data para o número do mês.
Si n t a x e
Retorno Descrição
233
D es c r i ç ã o
MONTH() é uma função de conversão que extrai da data o valor numérico do mês.
CMONTH() é uma função semelhante que retorna o nome do mês a partir do valor de dDa ta.
Ex e m p l o s
MsCompress
Compacta um ou vários arquivos em um único arquivo com extensão .MZP.
Si n t a x e
Ou
Retorno Descrição
234
D es c r i ç ã o
MSCOMPRESS() compacta os arquivos informados em um único arquivo com extensão default .MZP. O
formato é proprietário e multiplataforma.
Caso a senha seja informada apenas com a senha poderemos descompactar os arquivos.
Ex e m p l o s
MsCRC32
Calcula um CRC de uma string.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
MSCRC32() calcula um CRC de uma string informada e retorna um número com esse cálculo.
Note que strings iguais retornam CRC iguais, porém, nem sempre strings diferentes retornam CRC
diferentes.
235
Ex e m p l o
MsCRC32St r
Calcula um CRC de uma string, retornando em formato String.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
MSCRC32STR() calcula um CRC de uma string informada e retornando uma string com esse cálculo.
Note que strings iguais retornam CRC iguais, porém nem sempre strings diferentes retornam CRC
diferentes.
Ex e m p l o
MsDecomp
Descompacta arquivos no formato .MZP (Microsiga Zip).
236
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Caso o arquivo seja protegido por senha, apenas com a senha poderemos descompactá-lo.
Ex e m p l o
OrdCondSet
Seta a condição e o escopo para a ordem corrente.
237
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para setar uma ordem de registro que esteja dentro de um escopo e de uma
condição especificada. Se todos os parâmetros forem omitidos serão aceitos todos os registros da ordem.
Através do primeiro parâmetro (cForCond) é possível especificar o escopo ao qual o registro deve
pertencer para estar dentro do filtro. Através do parâmetro bEval, pode-se definir um bloco de código que
deve retornar .T. para que o registro pertença ao filtro a ser setado.
Se o parâmetro lDescendente for omitido, a ordem estará crescente, mas se tiver valor .T. será
decrescente.
Ex e m p l o
// Este exemplo mostra como se pode usar o ORDCONDSET para executar um filtro com idade
entre 20 e 30 anos e nome Joao:
USE Cliente VIA "DBFCDX" NEW
ORDCONDSET("Idade>20 .AND. Idade<30",,,,{||Nome = "Joao"})
OrdCreate
Cria uma ordem em determinado arquivo de índice.
238
Si n t a x e
ORDCREATE([ cIndice ],[ cOrde m ], cExpChave, [ bEx pChave ], [ lUnico ]) --> Nil
L
lUnico Não Cria índice como único (o padrão é .F.).
*Obs: Os dois primeiros parâmetros são opcionais, mas pelo menos um deles tem que estar especificado.
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para criar uma nova ordem em determinado arquivo de índice com o nome
especificado através do primeiro parâmetro, sendo que, se o mesmo existir, é apenas acrescentada a
ordem, mas, caso contrário, é criado o arquivo.
239
Com exceção do RDD Ctree, a tabela corrente não precisa estar aberta em modo exclusivo para a criação
da ordem, pois na criação de índices no Ctree é alterada a estrutura da tabela, sendo necessário que a
tabela esteja aberta em modo exclusivo.
Ex e m p l o
// Este exemplo mostra como se pode criar novo arquivo de índice criando a ordem sobre os
campos Nome e End e não aceitará duplicação:
USE Cliente VIA "DBFCDX" NEW
ORDCREATE ("\teste\ind2.cdx",,"Nome+End",{ || Nome+End },.T.)
// Este exemplo mostra como se pode criar nova ordem (Tag2) sobre o campo End que
aceitará duplicação e no arquivo de índice já existente:
USE Cliente VIA "DBFCDX" NEW
ORDCREATE ("\teste\ind2.cdx","Tag2","End",{ || End })
OrdDescend
Verifica ou altera a condição (crescente/decrescente) de uma ordem.
Si n t a x e
lDecrescente Não L
Determina se a ordem será decrescente (.T.) ou crescente (.F.)
Retorno Descrição
D es c r i ç ã o
Esta função pode ser utilizada para apenas verificar o estado da ordem atual, se não for especificado o
parâmetro lDecrescente.
240
Quando é especificado o parâmetro lDescend, o estado da ordem é modificado, sendo que a função
retorna ao estado anterior da ordem em questão.
Para evitar conflito, no caso de haver mais de uma ordem com o mesmo nome, pode-se passar o
parâmetro com o nome do índice ao qual a ordem pertence.
A ordem passada no primeiro parâmetro pode ser especificada através da sua posição na lista de ordens
ativas (através do ORDLISTADD) ou através do nome dado à ordem, a função verifica automaticamente
se o parâmetro é numérico ou caracter.
Ex e m p l o
// Este exemplo mostra como o ORDBAGNAME pode encontrar o nome de diferentes índices
através da posição da ordem na lista:
USE Cliente VIA "DBFCDX" NEW
ORDLISTADD ("\teste\ind1.cdx","NOME") // A ordem é criada na forma crescente
ORDDESCEND() // Retorna: .F.
ORDDESCEND(,,.T.) // Retorna: .F., mas seta a ordem atual (NOME) como decrescente
ORDDESCEND() // Retorna: .T.
ORDLISTADD ("\teste\ind2.cdx","NOME")
ORDDESCEND("NOME","ind1",.F.) // Retorna: .T.
ORDDESCEND("NOME","ind1",) // Retorna: .F.
OrdKey
Verifica qual a expressão de chave da ordem.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
241
Esta função é utilizada para verificar qual é a expressão de chave de determinada ordem.
Caso não sejam especificados os parâmetros de identificação da ordem, é verificada a ordem corrente.
Para evitar conflito, no caso de haver mais de uma ordem com o mesmo nome, pode-se passar o
parâmetro com o nome do índice ao qual a ordem pertence.
A ordem passada no primeiro parâmetro pode ser especificada através da sua posição na lista de ordens
ativas (através do ORDLISTADD) ou através do nome dado à ordem, a função verifica automaticamente
se o parâmetro é numérico ou caracter.
Ex e m p l o
// Este exemplo mostra como o ORDKEY() pode recuperar a expressão da ordem atual:
USE Cliente NEW
INDEX ON Nome+Cod TO Ind1 FOR Nome+Cod > "AZZZZZZZ"
ORDKEY("Ind1") // Retorna: Nome+Cod
OrdListAdd
Acrescenta uma ou mais ordens à lista.
Si n t a x e
cArq Indice Sim C Nome do índice a ser acrescentado, com ou sem diretório e extensão
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para acrescentar uma ou mais ordens de determinado índice na lista de ordens
ativas da área de trabalho.
242
Quando são especificados os dois argumentos (índice e ordem), é acrescentada apenas a ordem
especificada nos parâmetros à lista e a mesma torna-se ativa.
Quando é especificado apenas o primeiro parâmetro, são acrescentadas todas as ordens contidas no
arquivo de índice especificado neste parâmetro à lista, e a primeira ordem torna-se ativa.
Para se utilizar arquivos de extensão padrão do RDD, este dado pode ser omitido no primeiro parâmetro,
mas, caso contrário, deve ser especificado.
Ex e m p l o
// Este exemplo mostra como se pode acrescentar uma ordem específica ou todas as ordens
de determinado arquivo de índice à lista:
USE Cliente VIA "DBFCDX" NEW
OrdListAdd ("\teste\ind1.cdx","NOME") // Acrescenta apenas a ordem NOME
OrdListAdd ("\teste\ind2.cdx") // Acrescenta todas as ordens do arquivo ind2.cdx
PRo w
Informa ou muda a linha corrente de impressão.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
PROW( ) pode ser utilizado para informar a linha corrente de impressão ou para modificá-la. Se a nova
linha informada for menor que a corrente, isto provocará um salto de página na impressão.
Ex e m p l o
243
Pack
Remove todos os registros deletados da tabela.
Si n t a x e
PACK
D es c r i ç ã o
Ex e m p l o
// Este exemplo demonstra como se pode utilizar a função DBDELETE() para marcar alguns
registros como deletados e o comando PACK para deletá-los fisicamente.
USE Clientes NEW
DBGOTO(100)
DBDELETE()
DBGOTO(105)
DBDELETE()
DBGOTO(110)
DBDELETE()
PACK
PCol
Informa ou muda a coluna corrente de impressão.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
PCOL( ) pode ser utilizado para informar a coluna corrente de impressão ou para modificá-la. Se for
informada uma coluna menor que a corrente, serão impressos caracteres de BACKSPACE chr(8) para
forçar o retorno do carro de impressão em impressoras matriciais.
244
Ex e m p l o
PCOL( 10 )
@ ROW( ), PCOL( ) PSAY "Minha Linha nesta pagina e " + str( PROW( ) )
PROW( PROW( )+2 ) // Pula 2 linhas
PCOL( 10 )
@ PROW( ), PCOL( ) PSAY "Minha Linha nesta pagina e " + str( PROW( ) )
PROW( 0 ) // Salta a pagina
PreparePrin t
Prepara o relatório para o inicio da impressão.
Si n t a x e
cFile Sim C Informa o nome de arquivo que será gerado se lDisco = .T..
Retorno Descrição
D es c r i ç ã o
245
Quando estamos utilizando um servidor em ambiente Unix, pode-se configurar a saída do relatório para
utilizar o LPD (Line Printer Daemon) do Unix. Ative o parâmetro l_lpd para .T., e no arquivo de
configuração do Server (AP6SRV.INI), crie a entrada abaixo:
[SERVERPRINTERS]
PRINTERSNAME=lp1,lp2[...,lp3]
Onde PRINTERSNAME é uma lista com os nomes das impressoras cadastradas no \etc\printcap. Para mais
informações veja manual do Unix para configuração de impressoras. Lembrando que o Unix é case-
sensitive quando trata nomes e arquivos.
Ex e m p l o
PrnFlush
Força envio do buffer de impressão para a impressora.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Nas impressões, o Protheus bufferiza a impressão em páginas para enviar todo o conteúdo para a
impressora de forma otimizada. PRNFLUSH( ) força o envio do buffer de dados para a impressora antes do
previsto pela otimização de impressão.
Ex e m p l o
246
RDDSetDefault
Modifica ou verifica o RDD padrão.
Si n t a x e
cNovoRddPad rão Não C Novo nome do RDD a ser definido como padrão.
Retorno Descrição
D es c r i ç ã o
Esta função pode ser utilizada apenas para verificar qual o RDD que está definido como padrão quando for
omitido seu parâmetro.
Ela também pode ser utilizada para especificar outro RDD como padrão, especificando-o através do
parâmetro.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o RDDSETDEFAULT para alterar o valor do
RDD padrão.
RDDSETDEFAULT("CTREECDX") // Retorna: DBFCDX
RDDSETDEFAULT() // Retorna: CTREECDX
RealRDD
Retorna qual é o driver que realmente está sendo utilizado para abertura dos arquivos locais.
Si n t a x e
Retorno Descrição
247
"CODEBASE" Codebase
D es c r i ç ã o
O driver "DBFCDX" pode ser utilizado para a abertura de arquivos Codebase, Advantage Database Server,
Advantage Local Server ou Ctree. Depende do que está especificado na chave LOCALFILES do ambiente
utilizado, no arquivo de inicialização do servidor.
REALRDD() retorna o nome do driver que realmente está sendo utilizado para abertura dos arquivos
locais.
Ex e m p l o
if RealRdd()="CODEBASE"
conout("Mudar abertura dos arquivos para ADS.")
endif
Recall
Altera o estado deletado de alguns registros.
Si n t a x e
RECALL [FOR CondFor] [WHILE CondWhile] [NEXT nRecs] [RECORD nRecno] [REST] [ALL]
Retorno Descrição
248
D es c r i ç ã o
Este comando é utilizado para retirar a marca de registro deletado de alguns registros.
Para ser executado, os registros em questão devem estar bloqueados ou a tabela deve estar aberta em
modo exclusivo. Se o registro não estiver deletado, este comando não faz nada.
Ele é o oposto da função DBDELETE, que marca o registro atual como deletado.
• se todas as opções forem omitidas ele é executado apenas para o registro atual;
• se for especificada uma condição de "FOR", o escopo abrange todos os arquivos ("ALL");
• o parâmetro "RECORD nRecno" especifica qual recno do registro deve ser alterado;
• a opção "REST" determina que serão processados os registros a partir do registro atual. Caso seja
omitida, o comando começa a processar a partir do primeiro registro.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o RECALL para retornar o estado do
registro atual para normal.
USE Cliente
DBGOTO(100)
DBDELETE()
DELETED() // Retorna: .T.
RECALL
DELETED() // Retorna: .F.
// Este exemplo demonstra como se pode utilizar o RECALL para retornar o estado de todos
os registros que apresentam idade>30.
USE Cliente
RECALL FOR Idade>30
// Este exemplo demonstra como se pode utilizar o RECALL para retornar o estado de todos
os registros com idade maior que 30 e Nome = Joao a partir do registro atual.
USE Cliente
RECALL FOR Idade>30 WHILE Nome="Joao" REST
RecSize
Verifica o tamanho do registro da tabela corrente.
Si n t a x e
249
Retorno Descrição
D es c r i ç ã o
Esta função calcula o tamanho do registro da tabela corrente somando os tamanhos de cada campo mais
um byte da flag de registro deletado mais quatro bytes do campo recno.
Ela pode ser utilizada em conjunto com as funções Header e RecCount para calcular o tamanho ocupado
no disco pela tabela corrente, pois o tamanho será Header+RecSize*RecCount.
Ex e m p l o
// Este exemplo calcula o tamanho ocupado pela tabela "AA1990.DBF" no disco (número de
bytes):
USE "\DADOSADV\AA1990.DBF" SHARED NEW
nCabecalho := HEADER()
nDados := RECSIZE() * RECCOUNT()
nTamanhoTotal := nCabecalho + nDados
Re I ndex
Reconstrói todos os índices abertos da área de trabalho corrente.
Si n t a x e
REINDEX
D es c r i ç ã o
Este comando reconstrói todos os índices da área de trabalho corrente e posiciona as tabelas no primeiro
registro lógico.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o DBREINDEX para reconstruir os índices
depois que um novo índice foi gerado.
USE Clientes NEW
DBSETINDEX("IndNome")
REINDEX
Replace
250
Si n t a x e
REPLACE Campo WITH Ex p [, Campo2 WITH Ex p2 …] [FOR CondFor] [WHILE CondWhile] [NEXT
nRecs] [RECORD nRecno] [REST] [ALL]
Exp Sim Expressão em ADVPL com valor a ser colocado no campo especificado
CondFor Não Expressão em ADVPL a ser resolvida para que o registro seja alterado
N
nRecs Não Quando registros devem ser alterados
D es c r i ç ã o
Este comando é utilizado para alterar o valor de determinado campo em alguns registros da tabela
corrente, onde o campo escolhido recebe o valor da expressão para os registros dentro do escopo
definido.
Se não forem especificadas as condições para que o registro seja alterado, modifica toda a tabela, como
se estivesse especificada a opção "ALL".
Pode-se especificar um escopo para que os registros sejam alterados através das opções "FOR CondFor" e
"WHILE CondWhile".
Pode-se também limitar o número de registros a serem alterados através da opção "NEXT nRecs" e
determinar que a alteração dos registros deve-se iniciar a partir do registro atual com "REST", mas, caso
contrário, o comando executa um DBGOTOP() antes de iniciar a alteração.
Se é desejado alterar apenas determinado registro pode-se defini-lo através da especificação do recno
com "RECORD nRecno".
Ex e m p l o
// Este exemplo demonstra como utilizar o comando REPLACE alterar todos os registros
dentro do escopo, onde o campo "Valor" receberá "Valor1+Valor2-Valor3*0.1" e o campo
"DiaTran" receberá a data atual. Este escopo é definido por Idade > 20, até que o nome
seja maior ou igual a "VVV", começa a deleção a partir do registro atual e marca apenas
10 registros:
251
RLock
Bloqueia o registro corrente da tabela ativa.
Si n t a x e
Retorno Descrição
.F. Não conseguiu bloquear o registro. Principal motivo: o registro já está bloqueado por outro
usuário.
D es c r i ç ã o
Esta função é utilizada quando se tem uma tabela aberta e compartilhada, e se deseja bloquear um
registro para que outros usuários não possam alterá-lo. Se a tabela já está aberta em modo exclusivo, a
função não altera seu estado.
Ex e m p l o
//Este exemplo utiliza a função RLOCK() para deletar o registro com o nome "Joao" da tabela de Clientes
indexada por Nome:
252
Seconds
Retorna o número de segundos decorridos desde a meia-noite.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função retorna o número de segundos decorridos desde a meia-noite, segundo a hora do sistema.
Está relacionada à função TIME() que retorna a hora do sistema como uma cadeia de caracteres no
formato hh:mm:ss.
Ex e m p l o s
Seek
Encontra um registro com determinado valor da chave do índice.
Si n t a x e
253
Retorno Descrição
D es c r i ç ã o
Este comando é utilizado para encontrar um registro com determinado valor da expressão de chave de
índice.
Antes da chamada do SEEK deve-se certificar de que existe uma ordem ativa no momento com os campos
que se deseja pesquisar o valor.
Caso a expressão possua apenas um campo numérico, o primeiro parâmetro deve ser do tipo numérico,
mas nos demais casos deve-se utilizar um valor do tipo caracter para este parâmetro (mesmo se forem
apenas dois campos numéricos ou do tipo data).
Quando for especificada a opção "SOFTSEEK", mesmo que a expressão pesquisada não encontrar nenhum
registro com este valor, a tabela será posicionada no próximo valor maior que o especificado no primeiro
parâmetro, mas mesmo posicionando no próximo valor, esta função retornará .F. (pois não encontrou).
Quando não for especificado este valor ou estiver .F. e falhar o valor de pesquisa, a tabela será
posicionada em LASTREC + 1 e será setada a flag de EOF.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o SEEK para busca de valores numéricos.
USE Clientes NEW
ORDLISTADD ("/teste/ind1.cdx") // Expressão é Num (campo numérico)
SEEK 100 // Retorna: .F.
EOF() // Retorna: .T.
SEEK 100 SOFTSEEK // Retorna: .F.
EOF() // Retorna: .F. (pois o softseek posicionou no próximo registro)
// Este exemplo demonstra como se pode utilizar o SEEK para percorrer todos os registros
de Clientes com o nome joao e vencimentos a partir de janeiro de 2001.
USE Clientes NEW
ORDLISTADD ("/teste/ind2.cdx") // Expressão é Nome+Venc (campo caracter + data)
SEEK " joao200101" SOFTSEEK // Procura a primeira ocorrência de Nome "joao" e
vencimento maior que Janeiro de 2001
WHILE !EOF() .AND. Nome == " joao"
DBSKIP()
ENDDO
Select
Seleciona nova área de trabalho.
Si n t a x e
254
D es c r i ç ã o
Este comando é utilizado para selecionar uma nova área de trabalho para deixá-la ativa.
Ex e m p l o
// Este exemplo demonstra como se pode utilizar o SELECT alterar a área corrente.
USE Clientes ALIAS a1
USE Clientes2 ALIAS a2
SELECT a1 // ou SELECT 1
Si n t a x e
Condição Não Expressão em ADVPL a ser setada como filtro na ordem corrente
Retorno Descrição
D es c r i ç ã o
Este comando é utilizado para setar um filtro nos registros da tabela corrente especificado através da
condição especificada.
Quando um registro não está dentro do filtro setado ele continua existindo fisicamente, mas não
logicamente (nas funções de manipulação de banco de dados como DBGOTOP, DBSEEK , DBSKIP, etc).
255
Ex e m p l o
// Este exemplo demonstra como utilizar o comando SET FILTER para setar novas expressões
de filtro e retirá-las:
USE Cliente VIA "CTREECDX" NEW
SET ORDER TO 2 // Seta a ordem de nome Nome do índice Ind1
SET FILTER TO Idade>30 // Filtra os registros com Idade menor que 30
SET FILTER TO
Set I ndex
Acrescenta todas as ordens de um ou mais arquivos de índice à lista.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Este comando é utilizado para acrescentar uma ou mais ordens de determinado índice na lista de ordens
ativas da área de trabalho quando se especifica "ADDITIVE".
Quando o mesmo é omitido, a lista de ordens é esvaziada para depois ser acrescentada às ordens dos
índices.
Quando o arquivo de índice possui apenas uma ordem, a mesma é acrescentada à lista e torna-se ativa.
Quando o índice possui mais de uma ordem, todas são acrescentadas à lista e a primeira torna-se ativa.
Quando mais de um arquivo de índice é selecionado, a ordem que torna-se ativa é a primeira ordem do
primeiro arquivo.
256
Quando o comando é utilizado sem nenhum parâmetro, todas as ordens da lista são apagadas.
Ex e m p l o
// Este exemplo demonstra como utilizar o comando SET INDEX para acrescentar novas ordens
a lista e retirá-las depois:
USE Cliente VIA "CTREECDX" NEW
SET INDEX TO ind1 // Inicializa a lista com as ordens do arquivo de índice "ind1"
SET INDEX TO ind2 ADDITIVE // Acrescenta as ordens do arquivo de índice "ind2" na lista
SET INDEX TO ind3 // Limpa a lista e inicializa com as ordens do arquivo "ind3"
SET INDEX TO // Limpa a lista de ordens
Set Order
Seleciona uma ordem ativa da área de trabalho.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Este comando pode ser utilizado apenas para retornar a tabela corrente à ordem original (recno), se não
for especificado nenhum parâmetro.
Também pode ser utilizado para selecionar uma nova ordem para a tabela corrente através da posição da
ordem na lista de ordens ativas com o primeiro parâmetro ou através do nome da ordem especificado
"TAG cOrde m".
Para evitar nomes de ordens duplicados, pode-se especificar a qual arquivo de índice pertence com "IN
cIndice".
257
Ex e m p l o
// Este exemplo demonstra como utilizar o comando SET ORDER para setar novas ordens e
retirá-las:
USE Cliente VIA "CTREECDX" NEW
SET ORDER TO TAG Nome IN Ind1 // Seta a ordem de nome Nome do índice Ind1
SET ORDER TO 3 // Seta a terceira ordem da lista
SET ORDER TO // Retira as ordens, setando a ordem natural da tabela
SetPrc
Configura a linha e coluna correntes de impressão.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
SETPRC( ) modifica a linha e coluna atuais de impressão assim como PCOL( ) e PROW( ) chamados
separadamente.
Ex e m p l o
Skip
Desloca a tabela para outro registro.
258
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Este comando é utilizado para deslocar para outro registro a partir do registro atual.
O parâmetro especifica quantos registros lógicos devem ser deslocados a partir do corrente. Se for
positivo desloca em direção ao final da tabela, se for negativo ao início da tabela e, caso seja omitido, irá
para o próximo registro (o padrão é 1). Caso passe do início da tabela, posiciona no primeiro registro e
seta BOF, caso passe do final da tabela, posiciona no registro LASTREC + 1 e seta EOF.
O padrão é ser utilizado para a tabela corrente, mas pode ser especificada outra área de trabalho para
executá-lo através do número "nArea" ou nome "ALIAS Alias".
Ex e m p l o
// Este exemplo mostra como o SKIP pode passar do final da tabela e do início da tabela
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBGOBOTTOM()
EOF() // retorna .F.
SKIP
EOF() // retorna .T.
DBGOTOP()
BOF() // retorna .F.
SKIP -1
BOF() // retorna .T.
// Este exemplo mostra como o SKIP pode deslocar 10 registro em relação ao registro
corrente
DBUSEAREA(.T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBGOTO(100)
SKIP 10
RECNO() // retorna 110
SKIP -10
RECNO() // retorna 100
// Este exemplo mostra como o SKIP pode ser executado em outra area de trabalho.
DBUSEAREA(.T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
259
DBGOTO(100)
DBUSEAREA(.T.,"dbfcdxads", "\dadosadv609\sa1110.dbf","XXX", .T., .F. )
SKIP 10 ALIAS "SSS"
SSS->RECNO() // retorna 110
SKIP -10 ALIAS "SSS"
SSS->RECNO() // retorna 100
Spli tPat h
Quebra em diversas partes um arquivo.
Si n t a x e
SPLITPATH( cArq, @[cDrive], @[cCa minho], @[cNo me], @[cEx t] ) --> NIL
Retorno Descrição
D es c r i ç ã o
SplitPath() divide um caminho completo em todas as suas subpartes; cArq não necessita conter todas as
partes.
Tanto arquivos locais ( Remote ) quanto arquivos no servidor, podem ser informados.
260
Ex e m p l o
TCConType
Define o tipo de conexão que será utilizada entre o Protheus e o TopConnect.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Determina o tipo de conexão que será utilizada entre o Protheus e o TopConnect. O valor é guardado e
utilizado nas chamadas seguintes de TCLink.
Ex e m p l o
TCConType("NPIPE")
_nCon := TCLink("MSSQL7/TOPSQL", "TOPSERVER1")
If (_nCon < 0)
CONOUT("Falha Conexao TOPCONN - Erro: "+ str(nCon, 10, 0))
EndIf
261
TCDelFile
Apaga um arquivo de um banco de dados.
Si n t a x e
Retorno Descrição
.F. Erro. Geralmente é porque a tabela está sendo utilizada por outro processo.
D es c r i ç ã o
Ex e m p l o
If TcCanOpen("TRB"+SM0->M0_CODIGO+"0")
TcDelFile("TRB"+SM0->M0_CODIGO+"0")
Endif
TCGenQry
Define a execução de uma Query.
Si n t a x e
xPar1, xPar2 Não Qualquer Parâmetros apenas para compatibilização. Não tem função.
Retorno Descrição
262
D es c r i ç ã o
Esta função determina que a próxima chamada à DBUseArea será a abertura de uma Query e não de
tabela.
Ex e m p l o
TCI svLock
Verifica se o servidor possui sistema de locks virtuais.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Através de locks virtuais, é possível bloquear uma string. A função TCISVLOCK verifica se o servidor
TopConnect possui tratamento para locks virtuais.
Ex e m p l o
#ifdef TOP
If TCIsVLock()
TCVUnLock()
EndIf
#endif
TCRefresh
Faz refresh em uma tabela.
263
Si n t a x e
cTabela Sim Lógico Indica nome da tabela que deve ser feito refresh.
Retorno Descrição
D es c r i ç ã o
Faz o refresh de uma tabela, através de uma leitura forçada da tabela no banco de dados. É útil após
alterações diretas no banco (delete, insert).
Ex e m p l o
cTabela:= "SA1990"
cComando := "Delete "+ cTabela +" Where R_E_C_N_O_ > 50000 "
TCSqlExec(cComando)
TCRefresh(cTabela)
TCSetBuff
Esta função foi mantida apenas para compatilização, não sendo utilizada no AP6.
TCSetConn
Altera a conexão corrente.
Si n t a x e
Retorno Descrição
264
D es c r i ç ã o
Altera a conexão corrente. Novas tabelas abertas ou criadas utilizarão esta conexão para realizar a
operação. É útil quando se tem mais de uma conexão com o TopConnect.
Ex e m p l o
TCSetDummy
Altera o status do modo "dummy"
Si n t a x e
lStat us Sim Lógico Indica se deve ligar (.T.) ou desligar (.F.) o modo "dummy" .
Retorno Descrição
D es c r i ç ã o
265
No modo "dummy", o TopConnect faz apenas a abertura dos arquivos, sem executar nenhuma função de
posicionamento. É utilizado para fazer uma abertura mais rápida dos arquivos. Passando .T., entra em
modo "Dummy", .F. volta ao normal.
Ex e m p l o
TCSetDummy(.t.)
For ni:= 1 to NroTabelas
cTabela:= "TABELA"+TRIM(STR(NI, 10, 0))
dbUseArea( .T.,"TOPCONN", cTabela, cTabela, .T., .F. )
next
TCSetDummy(.F.)
dbselectarea("TABELA1")
DBGOTOP()
.......
TCSetField
Altera o tipo de um campo.
Si n t a x e
Novo tipo do campo. Pode ser : 'N' (numérico), 'D' (data) ou 'L'
cTipo Sim C
(lógico).
N
nDecimais Não Decimais do campo. Só é utilizado se o campo for numérico.
Retorno Descrição
D es c r i ç ã o
Quando se faz a abertura de uma tabela via TCquery, todos os campos aparecem como tipo Caracter. É
necessário em seguida acertar o tipo do campo, se ele não for caracter.
Ex e m p l o
aStru := CT2->(dbStruct())
266
cCond := ".T."
cQuery := "SELECT * FROM " + RetSqlName("CT2") + " WHERE"
cQuery := 'CT2_FILIAL = "' + xFilial("CT2") EndIf
cQuery := ChangeQuery(cQuery)
dbUseArea(.T., "TOPCONN", TCGenQry(,,cQuery), 'NovoCT2', .F., .T.)
For ni := 1 to Len(aStru)
If aStru[ni,2] != 'C'
TCSetField('NovoCT2', aStru[ni,1], aStru[ni,2],aStru[ni,3],aStru[ni,4])
Endif
Next
TCSpExec
Executa uma Stored Procedure.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Executa uma Stored Procedure, no banco de dados, com número variável de parâmetros.
Ex e m p l o
267
Para executar:
TCSpExist
Verifica se uma Stored Procedure existe.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
if TCSPExist("SP000001")
cStr := "DROP PROCEDURE "+ "SP000001 "
TCSqlExec(cStr)
endif
268
TCSqlError
Retorna o último erro produzido em comandos SQL.
Si n t a x e
Retorno Descrição
Caracter Texto com descrição do erro. Se não houve erro, retorna texto vazio.
D es c r i ç ã o
Esta função obtém as mensagens de erros em ordem inversa. Portanto, às vezes é necessário fazer várias
chamadas a esta função para obter todos os erros, caso eles sejam múltiplos.
Ex e m p l o
TCSrvType
Retorna o tipo de servidor.
Si n t a x e
Retorno Descrição
<> "" String contendo o tipo do servidor. Pode ser: "AS/400", "WinNT", "AIX", "HPUX","Linux"
269
D es c r i ç ã o
Ex e m p l o
// É utilizado para testar se o ambiente é AS/400, pois alguns comandos são diferentes
nesta plataforma.
Ex: Chamada da funcao de reconciliação
If TcSrvType() == 'AS/400'
Processa({|lEnd| FA210Processa()})
Else
Processa({|lEnd| FA211Processa()})
Endif
TCSysExe
Executa um comando do sistema operacional no servidor TopConnect.
Si n t a x e
Retorno Descrição
Ex e m p l o
270
;TCUnLink
Finaliza uma conexão com o TopConnect.
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Finaliza a conexão especificada com o TopConnect. Se não passar parâmetro, finaliza a conexão corrente.
O número da conexão é a retornada pela função <@>TCLink.
Ex e m p l o
TCVUnLock
Libera o bloqueio virtual de uma string.
Si n t a x e
271
String que deve ser liberada. Se não for passada, TODOS os locks
cPalav ra Não C
virtuais desta conexão são liberados.
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
#ifdef TOP
If TCIsVLock()
if !TCVLock("Processo1")
messagebox("Nao foi possivel bloquear o processo1", "", 0)
return
endif
...... // Processa
TCVUnlock("Processo1")
EndIf
#endif
TCVLock
Bloqueia uma string através de lock virtual.
Si n t a x e
272
Retorno Descrição
D es c r i ç ã o
Ex e m p l o
#ifdef TOP
If TCIsVLock()
if !TCVLock("Processo1")
messagebox("Nao foi possivel bloquear o processo1", "", 0)
endif
EndIf
#endif
Time
Retorna a hora do sistema
Si n t a x e
Retorno Descrição
D es c r i ç ã o
TIME() é uma função que retorna a hora do sistema como uma cadeia de caracteres. TIME() está
relacionada com SECONDS() que retorna o valor inteiro representando o número de segundos desde a
meia-noite.
Ex e m p l o s
Estes exemplos mostram a função TIME() utilizada em conjunto com SUBSTR() para extrair a hora, os
minutos e os segundos:
273
UnLock
Desbloqueia os registros da tabela corrente.
Si n t a x e
UnLock [ALL]
D es c r i ç ã o
Este comando é utilizado para liberar registros da tabela corrente. Se for passada a opção "ALL" todos os
registros da tabela corrente são liberados. Caso contrário, só é liberado o registro corrente.
Ex e m p l o
// Este exemplo mostra como liberar todos os registros bloqueados da tabela corrente.
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
UNLOCK ALL
// Este exemplo mostra uma variação do uso de UNLOCK para liberar apenas o registro
corrente.
DBUSEAREA( .T.,"dbfcdxads", "\dadosadv609\sa1990.dbf","SSS", .T., .F. )
DBGOTO(100)
UNLOCK // Desbloqueia o registro atual (100)
Update I n tName
Atualiza o nome do índice interno da tabela CTree.
Si n t a x e
Retorno Descrição
274
D es c r i ç ã o
A função UpdateIntName muda o nome do arquivo de índice interno de uma tabela Ctree, estando a
mesma fechada. Para tanto ela executa os seguintes passos:
1- Abre a tabela;
3- Fecha a tabela;
O nome do índice interno, que é armazenado no diretório "\CTREEINT\" acima da tabela equivalente, é
calculado da seguinte forma:
xxxxxxxxeeeYYYYMMDDhhmmss.int, sendo:
Na próxima vez em que a tabela é aberta, o arquivo deste novo índice será criado automaticamente.
Ex e m p l o
Use
275
Si n t a x e
USE Tabela [INDEX Indices] [ALIAS Alias] [EXCLUSIVE | SHARED] [NEW] [READONLY] [VIA Driver]]
Retorno Descrição
D es c r i ç ã o
Este comando associa uma tabela especificada pelo primeiro parâmetro (Tabela) à área de trabalho atual
através de um driver especificado através do parâmetro Driver.
No caso do Ctree os arquivos de índices permanentes já são abertos automaticamente, mas nos demais
RDDs deve especificar os arquivos de índices que se deseja abrir através do parâmetro Indices.
O Alias pode ser especificado através do parâmetro Alias. Pode-se especificar se a tabela será aberta em
modo exclusivo ou compartilhado (através das opções "EXCLUSIV" e "SHARED").
O usuário pode optar por abrir a tabela em modo somente leitura através da opção "READONLY", onde
nenhuma alteração será efetivada na tabela. A opção "NEW" determina que a tabela especificada será
aberta na próxima área de trabalho disponível e será setada como a área de trabalho corrente.
Ex e m p l o
// Este exemplo demonstra como utilizar o comando USE para associar uma tabela (do tipo
Ctree) a próxima área de trabalho disponível e torná-la ativa em modo compartilhado e
somente leitura:
USE Cliente VIA "CTREECDX" NEW SHARED READONLY
276
Used
Verifica se existe uma tabela corrente
Si n t a x e
Retorno Descrição
D es c r i ç ã o
Esta função é utilizada para verificar se existe alguma tabela aberta no momento.
Ex e m p l o
//Este exemplo utiliza a função USED()para verificar quando a tabela está ativa:
USE Clientes NEW
Result := USED() // Result: .T.
CLOSE
Result := USED() // Result: .F.
Year
Converte o valor da data no valor numérico do ano.
Si n t a x e
Retorno Descrição
277
D es c r i ç ã o
YEAR() é uma função de conversão de data que extrai o valor numérico do ano. YEAR() é membro de um
grupo de funções que retornam valores numéricos de uma data. O grupo inclui DAY() e MONTH() que
retornam o dia e o mês como valores numéricos.
Ex e m p l o s
Este exemplo cria uma função de usuário que usa a função YEAR() para formatar o valor da data:
ZAP
Remove todos os registros da tabela.
Si n t a x e
ZAP
D es c r i ç ã o
Ex e m p l o
278
tSrvObject
Classe mãe de todas as classes de interface.
Característ icas
Classe abstrata inicial de todas as classes de interface do Advpl. Não deve ser instanciada diretamente.
Propriedades
lShowHint Lógico. Flag que ativa .T. ou desativa .F. a exibição do tooltip do objeto.
Caractere. Mensagem exibida na barra de status da janela principal quando o objeto ganha
cMsg
foco.
279
Métodos
SetFocus
Sintaxe
SetFocus( )
Descrição
Retorno
NIL
Hide
Sintaxe
Hide( )
Descrição
Retorno
NIL
Sho w
Sintaxe
Show( )
Descrição
Retorno
NIL
Enable
Sintaxe
Enable( )
280
Descrição
Habilita o objeto.
Retorno
NIL
Disab le
Sintaxe
Disable( )
Descrição
Desabilita o objeto.
Retorno
NIL
Ref resh
Sintaxe
Refresh( )
Descrição
Classes de Janelas
t Windo w
Classe de janela principal de programa.
Hierar quia
Característ icas
281
Classe de janela principal de programa, deverá existir apenas uma instância deste objeto na execução do
programa.
Propriedades
oCtlFocus Objeto. Objeto contido na janela que está com foco de entrada de dados.
Métodos
New
Descrição
Sintaxe
Parâmetros
nPar6 Reservado.
oPar7 Reservado.
oPar8 Reservado.
Reservado.
oPar9
282
cPar16 Reservado.
lPar17 Reservado.
lPar18
Reservado.
lPar19 Reservado.
lPar20 Reservado.
Lógico, opcional. Se .T. (padrão) considera coordenadas passadas em pixels, se .F.
AlPixel
considera caracteres.
Retorno
Act iva te
Descrição
Sintaxe
Activate([acShow], [bPar2], [bPar3], [bPar4], [bPar5], [bPar6], [ abInit ], [bPar8], [bPar9], [bPar10],
[bPar11], [bPar12] ,[bPar13], [bPar14], [bPar15], [abValid], [bPar17], [bPar18] ).
Parâmetros
bPar2 Reservado.
bPar3 Reservado.
bPar4 Reservado.
bPar5 Reservado.
bPar6
Reservado.
283
bPar17 Reservado.
bPar18 Reservado.
Retorno
NIL
End
Descrição
Sintaxe
End( )
Retorno
Cen ter
Descrição
Centraliza a janela.
Sintaxe
Center( )
Retorno
NIL
Exemplo
#include “protheus.ch”
Local oWindow
Local abInit:= {||msgstop(“ativando!”)}
Local abValid:= {|| msgstop(“encerrando!”),.T.}
oWindow:= tWindow():New( 10, 10, 200, 200, “Meu programa”;
,,,,,,,,CLR_WHITE,CLR_BLACK,,,,,,,.T. )
oWindow:Activate(“MAXIMIZED”,,,,,,abInit,,,,,,,,,abValid,,)
Return nil
TDialog
284
Hierar quia
Característ icas
Classe de janela de diálogo de entrada de dados, uso reservado, recomenda-se utilizar a classe MSDialog
que é herdada desta classe.
Propriedades
Métodos
New
Descrição
Sintaxe
Parâmetros
cPar6 Reservado.
nPar7 Reservado.
lPar8 Reservado.
nPar9 Reservado.
285
oPar12 Reservado.
Objeto, opcional. Janela mãe da janela a ser criada, padrão é a janela principal do
AoWnd
programa.
oPar15 Reservado.
oPar16 Reservado.
nPar17 Reservado.
Retorno
O Diálogo criado.
Act iva te
Descrição
Sintaxe
Parâmetros
bPar1 Reservado.
bPar2
Reservado.
bPar3 Reservado.
alCentered Lógico, opcional. Se .T. exibe a janela centralizada, .F. é padrão.
Bloco de código, opcional. Deve retornar .T. se conteúdo do diálogo é válido, se
AbValid
retornar .F. o diálogo não fechará quando solicitada de encerrar.
lPar6 Reservado.
AbInit Bloco de código, opcional. Executado quando o diálogo inicia exibição.
bPar8 Reservado.
bPar9 Reservado.
Retorno
NIL.
286
End
Descrição
Sintaxe
End( )
Retorno
MSDialog
Classe de diálogo de entrada de dados.
Hierar quia
Característ icas
MSDialog deve ser utilizada como padrão de janela para entrada de dados. MSDialog é um tipo de janela
diálogo modal, isto é, não permite que outra janela ativa receba dados enquanto esta estiver ativa.
Propriedades
Métodos
New
Descrição
Sintaxe
Parâmetros
287
cPar6 Reservado.
nPar7 Reservado.
lPar8 Reservado.
nPar9 Reservado.
anClrBack
Cor do fundo.
oPar12 Reservado.
AoWnd
Objeto, opcional. Janela pai do diálogo, geralmente a janela principal do programa.
Retorno
O diálogo construído.
Exemplo
#include “protheus.ch”
// cria diálogo
Local oDlg:=MSDialog():New(10,10,300,300,”Meu dialogo”;
,,,,,CLR_BLACK,CLR_WHITE,,,.T.)
Return
288
Classes Auxiliares
tFon t
Classe que encapsula fonte de edição.
Hierar quia
Descrição
Métodos
New
Descrição
Construtor do objeto.
Sintaxe
New([acName], [nPar2], [anHeight], [lPar4], [alBold], [nPar6], [lPar7], [nPar8], [alItalic], [alUnderline])
Parâmetros
nPar2 Reservado.
lPar4 Reservado.
nPar6 Reservado.
lPar7 Reservado.
nPar8 Reservado.
289
Retorno
O objeto criado.
Exem plo
#include “protheus.ch”
Return
tCon t rol
Classe abstrata mãe de todos os controles editáveis.
Hierar quia
Característ icas
Propriedades
290
lModified Lógico. Se .T. indica que o conteúdo da variável associada ao controle foi modificado.
hParent Numérico. Handle (identificador) do objeto sobre o qual o controle foi criado.
Métodos
SetFocus
Descrição
Sintaxe
SetFocus( )
Retorno
NIL
tBu t t on
Classe de botão.
Hierar quia
Descrição
Propriedades
291
Metodos
New
Descrição
Construtor da classe.
Sintaxe
Parâmetros
aoWnd Objeto, opcional. Janela ou controle onde o botão deverá ser criado.
Bloco de código, opcional. Bloco que deverá ser acionado quando o botão for
abAction
pressionado.
nPar8 Reservado.
Objeto, opcional. Objeto tipo tFont com propriedades da fonte utilizada para o título do
aoFont
botão.
Reservado.
lPar10
292
Exem plo
#include “protheus.ch”
Return nil
tCheckBox
Classe de caixa checkbox.
Hierar quia
Descrição
Utilize a classe tCheckbox quando desejar criar um controle que possua dois estados .T. ou .F..
Métodos
New
Descrição
Construtor da classe
Sintaxe
Parâmetros
293
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:= u,
abSetGet <var> ) } que o controle utiliza para atualizar a variável <var>. <var> deve ser tipo
lógico, se <var> = .T. então o controle aparecerá checado.
aoWnd Objeto, opcional. Janela ou controle onde o controle deverá ser criado.
nPar8 Reservado.
Objeto, opcional. Objeto tipo tFont com propriedades da fonte utilizada para o texto do
aoFont
controle.
Bloco de código, opcional. Executado quando o conteúdo do controle deve ser validado,
abValid
deve retornar .T. se o conteúdo for válido e .F. quando o conteúdo for inválido.
lPar14 Reservado.
cPar16 Reservado.
lPar17 Reservado.
Retorno
O objeto construído.
Exem plo
#include “protheus.ch”
294
100,20,,,,.T.)
ACTIVATE MSDIALOG oDlg CENTERED
If lCheck
MsgStop( “Funcionou!” )
endif
Return nil
tComboBox
Classe de combobox.
Hierar quia
Descrição
Utilize a classe tComboBox para cria uma entrada de dados com múltipla escolha com item definido em
uma lista vertical, acionada por F4 ou pelo botão esquerdo localizado na parte direita do controle. A
variável associada ao controle terá o valor de um dos itens selecionados ou no caso de uma lista
indexada, o valor de seu índice.
Propriedades
Array. Lista de itens, caracteres, a serem exibidos. Pode ter os seguintes formatos: a)
aItems Seqüencial, exemplo: {“item1”,”item2”,...,”itemN”} ou b) Indexada, exemplo:
{“a=item1”,”b=item2”, ..., “n=itemN”}.
Métodos
New
Descrição
Construtor da classe.
Sintaxe
Parâmetros
295
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:=
u, <var> ) } que o controle utiliza para atualizar a variável <var>. <var> deve ser
abSetGet tipo caracter. Se a lista for seqüencial, o controle atualizará <var> com o conteúdo do
item selecionado, se a lista for indexada, <var> será atualizada com o valor do índice
do item selecionado.
Array, opcional. Lista de items, caracteres, a serem exibidos. Pode ter os seguintes
anItems formatos: a) Seqüencial, exemplo: {“item1”,”item2”,...,”itemN”} ou b) Indexada,
exemplo: {“a=item1”,”b=item2”, ..., “n=itemN”}.
nPar8 Reservado.
abChange Bloco de código, opcional. Executado quando o controle modifica o item selecionado.
Bloco de código, opcional. Executado quando o conteúdo do controle deve ser
validado, deve retornar .T. se o conteúdo for válido e .F. quando o conteúdo for
abValid
inválido.
bPar20 Reservado.
cPar21 Reservado.
Caractere, opcional. Nome da variável que o controle deverá manipular, deverá ser a
acReadVar mesma variável informada no parâmetro abSetGet, e será o retorno da função
ReadVar( ).
Retorno
O objeto criado.
Selec t
Descrição
296
Sintaxe
Select( [anItem] )
Parâmetros
Retorno
NIL
Exem plo
#include “protheus.ch”
Return nil
tGet
Classe de controle para entrada de dados editáveis.
Hierar quia
Descrição
Use tGet para criar um controle que armazene ou altere o conteúdo de uma variável através de digitação.
O conteúdo da variável só é modicado quando o controle perde o foco de edição para outro controle.
Propriedades
297
Métodos
New
Descrição
Sintaxe
Parâmetros
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:=
abSetGet u, <var> ) } que o controle utiliza para atualizar a variável <var>. <var> deve ser
tipo caracter, numérico ou data.
Objeto, opcional. Objeto tipo tFont utilizado para definir as características da fonte
aoFont
utilizada para exibir o conteúdo do controle.
lPar12 Reservado.
oPar13 Reservado.
Lógico, opcional. Se .T. as coordenadas informadas são em pixels, se .F. são em
alPixel
caracteres.
cPar15 Reservado.
lPar16 Reservado.
298
Retorno
O controle construído.
Exem plo
#include “protheus.ch”
Return nil
tGroup
Classe de painel de grupo de controles.
Hierar quia
299
Descrição
Utilize a classe tGroup para criar um painel onde controles visuais podem ser agrupados ou classificados.
É criada uma borda com título em volta dos controles agrupados.
Métodos
New
Descrição
Construtor da classe.
Sintaxe
Parâmetros
lPar10 Reservado.
Retorno
O objeto criado.
Exem plo
#include “protheus.ch”
300
Return nil
tList box
Classe de lista de items.
Hierar quia
Descrição
Utilize a classe tListbox para criar uma janela com itens selecionáveis e barra de rolagem. Ao selecionar
um item, uma variável é atualizada com o conteúdo do item selecionado.
Parâme t ros
Métodos
New
Descrição
Contrutor da classe
Sintaxe
Parâmetros
301
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:=
abSetGet u, <var> )} que o controle utiliza para atualizar a variável <var>. <var> deve ser
tipo caracter ou numérica.
bPar20 Reservado.
lPar21 Reservado.
lPar22 Reservado.
Bloco de código, opcional. Executado quando acionado click do botão direito do
abRightClick
mouse sobre o controle.
Selec t
Descrição
Sintaxe
Select( [nItem] )
Parâmetros
302
Retorno
NIL
Add
Descrição
Sintaxe
Parâmetros
Retorno
NIL
Modify
Descrição
Sintaxe
Parâmetros
Retorno
NIL
Del
Descrição
303
Apaga um item.
Sintaxe
Del( nPos )
Parâmetros
Numérico, obrigatório. Posição a ser excluida, deve ser maior que 0 e menor ou igual que o
nPos
número de itens.
Retorno
NIL
Len
Descrição
Sintaxe
Len( )
Retorno
Reset
Descrição
Sintaxe
Reset( )
Retorno
NIL
Exem plo
#include “protheus.ch”
304
,aItems,100,100,,oDlg,,,,.T.)
ACTIVATE MSDIALOG oDlg CENTERED
Return nil
tMeter
Classe de régua de processamento.
Hierar quia
Descrição
Utilize a classe tMeter para criar um controle que exibe uma régua (gauge) de processamento,
descrevendo o andamento de um processo atraves da exibição de uma barra horizontal.
Parâme t ros
Métodos
New
Descrição
Contrutor da classe.
Sintaxe
Parâmetros
305
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:=
abSetGet u, <var> ) } que o controle utiliza para atualizar a variável <var>. <var> deve ser
tipo numérico.
lPar8 Reservado.
Lógico, opcional. Se .T. as coordenadas informadas são em pixels, se .F. são em
alPixel caracteres.
oPar10 Reservado.
cPar11 Reservado.
Lógico, opcional. Se .T. (padrão) não considera os passos de atualização em
alNoPerc
porcentagem.
anClrPane Numérico, opcional. Cor de fundo do controle.
nPar14 Reservado.
anClrBar Numérico, opcional. Cor da barra de andamento.
nPar16 Reservado.
lPar17 Reservado.
Retorno
O objeto construído.
Set
Descrição
Sintaxe
Set( [nVal] )
Parâmetros
Retorno
NIL
Exem plo
306
#include “protheus.ch”
Return nil
If lRunning
Return
Endif
lRunning:= .T.
// inicia a régua
oMeter:Set(0)
While .T. .and. !lStop
// pára 1 segundo
Sleep(1000)
// atualiza a pintura da janela, processa mensagens do windows
ProcessMessages()
// pega valor corrente da régua
nCurrent:= Eval(oMeter:bSetGet)
nCurrent+=10
// atualiza régua
oMeter:Set(nCurrent)
if nCurrent==oMeter:nTotal
Return
endif
Enddo
lRunning:= .F.
lStop:= .F.
Return
tMult iget
Classe de campo Memo de edição.
Hierar quia
Descrição
Utilize a classe tMultiget para criar controle de edição de texto de múltiplas linhas.
Propriedades
307
Métodos
New
Descrição
Construtor da classe.
Sintaxe
Parâmetros
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:=
abSetGet u, <var> ) } que o controle utiliza para atualizar a variável <var>. <var> deve ser
tipo caracter.
Objeto, opcional. Objeto tipo tFont utilizado para definir as características da fonte
aoFont
utilizada para exibir o conteúdo do controle.
308
lPar21 Reservado.
alNoBorder Lógico, opcional. Se .T. cria controle sem borda.
alNoVScroll Lógico, opcional. Se .T., habilita barra de rolagem vertical.
Retorno
O objeto construído.
EnableVScroll
Descrição
Sintaxe
EnableVScroll( lEnable )
Parâmetros
Retorno
NIL
EnableHScroll
Descrição
Sintaxe
EnableHScroll( lEnable )
Parâmetros
Retorno
NIL
309
Exem plo
#include “protheus.ch”
Return Nil
tPanel
Classe de painel estático.
Hierar quia
Descrição
Utilize a classe tPanel quando desejar criar um painel estático, onde podem ser criados outros controles
com o objetivo de organizar ou agrupar componentes visuais.
Métodos
New
Descrição
Construtor da classe.
Sintaxe
Parâmetros
310
lPar6 Reservado.
alLowered Lógico, opcional. Se .T. exibe o painel rebaixado em relação ao controle de fundo.
Retorno
O objeto construído.
Exem plo
#include “protheus.ch”
Return
tRadMenu
Classe de radio group.
Hierar quia
Descrição
Utilize a classe tRadMenu para criar um controle que possibilita escolha de item através de uma lista.
311
Propriedades
Métodos
New
Descrição
Construtor do objeto.
Sintaxe
Parâmetros
Bloco de código, opcional. Bloco de código no formato {|u| if( Pcount( )>0, <var>:=
abSetGet u, <var> ) } que o controle utiliza para atualizar a variável <var>. <var> deve ser
tipo numérico.
aPar6 Reservado.
lPar11 Reservado.
Bloco de código, opcional. Executado quando mudança de foco de entrada de dados
abWhen está sendo efetuada na janela onde o controle foi criado. O bloco deve retornar .T.
para que o controle permaneça habilitado, ou .F. se não.
anWidth Numérico, opcional. Largura do controle em pixels.
anHeight Numérico, opcional. Altura do controle em pixels.
Bloco de código, opcional. Executado quando o conteúdo do controle deva ser
abValid
validado, retornando .T. se o conteúdo for válido, e .F. quando inválido.
lPar16 Reservado.
312
Lpar17 Reservado.
Lógico, opcional. Se .T. as coordenadas informadas são em pixels, se .F. são em
alPixel
caracteres.
Retorno
O objeto construído.
Enable I tem
Descrição
Sintaxe
Parâmetros
Retorno
NIL
Exem plo
#include “protheus.ch”
Return nil
tSay
Classe de label.
Hierar quia
313
Descrição
O objeto tipo tSay exibe o conteúdo de texto estático sobre uma janela ou controle.
Parâme t ros
Métodos
New
Descrição
Sintaxe
New([anRow], [anCol], [abText], [aoWnd], [acPicture], [aoFont], [lPar7], [lPar8], [lPar9], [alPixels],
[anClrText], [anClrBack], [anWidth], [anHeight], [lPar15], [lPar16], [lPar17], [lPar18], [lPar19])
Parâmetros
Codeblock, opcional. Quando executado deve retornar uma cadeia de caracteres a ser
abText
exibida.
Objeto, opcional. Objeto tipo tFont para configuração do tipo de fonte que será
aoFont
utilizado para exibir o conteúdo.
lPar7 Reservado.
lPar8 Reservado.
lPar9 Reservado.
Lógico, opcional. Se .T. considera coordenadas passadas em pixels se .F., padrão,
alPixels considera as coordenadas passadas em caracteres.
314
Retorno
O controle criado.
SetTex t
Descrição
Sintaxe
SetText( [xVal] )
Parâmetros
Retorno
NIL
Exem plo
#include “protheus.ch”
Return
315
tScrollbox
Classe de área de scroll.
Hierar quia
Descrição
Utilize a classe tScrollbox para criar um painel com scroll deslizantes nas laterais do controle.
Métodos
New
Descrção
Construtor da classe
Sintaxe
Parâmetros
Retorno
O objeto criado.
Exem plo
316
#include “protheus.ch”
Return nil
317
I nf ra-est r u t ura
Bem-vindo à documentação das funções genéricas e objetos disponíveis no RPO padrão do Advanced
Protheus.
• Funções de Infra-Estrutura
MsGetDados
Objeto tipo lista com uma ou mais colunas para cadastramento de dados baseado em um vetor.
Ca r a c t e r ís t i c as
A MsGetDados precisa que sejam declaradas as variáveis abaixo sendo tipo Private:
aRotina.
Vetor com as rotinas que serão executadas na MBrowse e que definira o tipo de operação que esta sendo
executada (inclusão, alteração, exclusão, visualização, pesquisa, ...) no formato:
Elemento Conteúdo
1 Título
2 Rotina
3 Reservado
Operação (1 - pesquisa; 2 - visualização; 3 - inclusão; 4 - alteração;
4
5 - exclusão)
Acesso relacionado a rotina, se esta posição não for informada
5
nenhum acesso será validado
318
aHeader
Elemento Conteúdo
1 Título
2 Campo
3 Máscara
4 Tamanho
5 Decimal
6 Validação
7 Reservado
8 Tipo
9 Reservado
10 Reservado
aCols
Vetor com as linhas a serem editadas. As colunas devem ser construídas com base no aHeader mais uma
ultima com valor lógico que determina se a linha foi excluída.
lRefresh
Variável tipo lógica para uso reservado.
A MsGetDados cria a variável publica n que indica qual a linha posicionada do aCols.
As funções passadas como parâmetro para a MsGetDados (cLinhaOk, cTudoOk, ...) não poderão ser
declaradas como Static Function.
A consulta padrão, validação do usuário e gatilhos estarão habilitados se o campo estiver cadastrado no
Dicionário de Dados (SX3/SX7) e apresentar estas opções disponíveis.
Mé t o d o s
New
D es c r iç ã o
Sin ta xe
319
Argumentos Descrição
Ret o r n o
Objeto.
ForceRefresh
D es c r iç ã o
320
Si n t a x e
oObjeto:ForceRefresh()
Hide
D es c r iç ã o
Esconde a MsGetDados.
Sintaxe
oObjeto:Hide()
Show
D es c r iç ã o
Mostra a MsGetDados.
Sintaxe
oObjeto:Show()
Ex e m p l o
321
EndIf
DbSkip()
End
Aadd(aCols,Array(nUsado+1))
For nI := 1 To nUsado
aCols[1][nI] := CriaVar(aHeader[nI][2])
Next
aCols[1][nUsado+1] := .F.
DEFINE MSDIALOG oDlg TITLE "Exemplo" FROM 00,00 TO 300,400 PIXEL
oGetDados := MSGETDADOS():NEW(05, 05, 145, 195, 4, "U_LINHAOK", "U_TUDOOK",
"+A1_COD", .T., {"A1_NOME"}, , .F., 200, "U_FIELDOK", "U_SUPERDEL", , "U_DELOK", oDlg)
ACTIVATE MSDIALOG oDlg CENTERED
Return
MsGetDb
Objeto tipo lista com uma ou mais colunas para cadastramento de dados baseado em uma tabela
temporária.
Ca r a c t e r ís t i c as
A MsGetDB precisa que sejam declaradas as variáveis abaixo sendo tipo Private:
aRotina.
Vetor com as rotinas que serão executadas na MBrowse e que definira o tipo de operação que esta sendo
executada (inclusão, alteração, exclusão, visualização, pesquisa, ...) no formato:
Elemento Conteúdo
1 Título
2 Rotina
3 Reservado
Operação (1 - pesquisa; 2 - visualização; 3 - inclusão; 4 - alteração;
4
5 - exclusão)
322
aHeader
Elemento Conteúdo
1 Título
2 Campo
3 Máscara
4 Tamanho
5 Decimal
6 Validação
7 Reservado
8 Tipo
9 Reservado
10 Reservado
lRefresh
A tabela temporária utilizada pela MsGetDB deverá ser criada com base no aHeader mais um último
campo tipo lógico que determina se a linha foi excluída.
A MsGetDB cria a variável publica nBrLin que indica qual a linha posicionada do aCols.
As funções passadas como parâmetro para a MsGetDB (cLinhaOk, cTudoOk, ...) não poderão ser
declaradas como Static Function.
A consulta padrão, validação do usuário e gatilhos estarão habilitados se o campo estiver cadastrado no
Dicionário de Dados (SX3/SX7) e apresentar estas opções disponíveis.
Mé t o d o s
Ne w
D es c r iç ã o
Sin ta xe
323
Argumentos Descrição
Ret o r n o
324
Objeto.
Fo rc eRe f r es h
D es c r iç ã o
Sin ta xe
ForceRefresh()
Ex e m p l o
325
Return .T.
MsmGet
Conjunto de objetos tipo MsGet/MsCombo para cadastramento de dados baseado no Dicionário de Dados.
Ca r a c t e r ís t i c as
A MsMGet também poder criada a partir da função Enchoice a qual recebe os mesmos parâmetros do
método New porém não retorna o objeto criado.
A MsMGet se baseia no Dicionário de Dados para verificar campos obrigatórios, validações, gatilhos,
consulta padrão etc. assim como para a criação das Pastas de Cadastro.
A MsMGet pode usar tanto variáveis de memória do tipo Private como diretamente os campos da tabela a
que se refere.
Mé t o d o s
New
D es c r iç ã o
Sin ta xe
MSMGET():NEW( cAlias, nReg, nOpc, [ uPar1 ], [ uPar2 ], [ uPar3 ], [ aACho ], [ aPos ], [ aCpos ], [
uPar4 ], [ uPar5 ], [ uPar6 ], [ uPar7 ], [ oWnd ], [ uPar8 ], [ lMem oria ], [ lColuna ], [ uPar9 ], [
lSe mPastas ] ) -> objeto
Argumentos Descrição
326
Ret o r n o
Objeto.
Refresh
D es c r iç ã o
Sin ta xe
Refresh()
327
Hide
D es c r iç ã o
Esconde a MsMGet.
Sin ta xe
Hide()
Show
D es c r iç ã o
Mostra a MsMGet.
Sin ta xe
Show()
Ex e m p l o
328
Return
MBro wse
Monta um Browse com menu de opções.
Si n t a x e
MBROWSE( [ uPar1 ], [ uPar2 ], [ uPar3 ], [ uPar4 ], cAlias, [ aFix os ], [ cCpo ], [ uPar5 ], [ cFun ], [
nPad rao ], [ aCores ], [ cEx p Ini ], [ cExpFi m ], [ nCongela ] ) -> nil
D es c r i ç ã o
329
As variáveis cCadastro e aRotina (*) precisam ser declarados como private acima da chamada da função.
(*) vetor com as rotinas que serão executadas, nele será definido o tipo de operação a ser executada
(inclusão, alteração, exclusão, visualização, pesquisa, ...) sua estrutura é composta de 5 (cinco)
dimensões: 1º - Título; 2º – Rotina; 3º – Reservado; 4º – Operação (1 - pesquisa; 2 - visualização; 3 -
inclusão; 4 - alteração; 5 - exclusão); 5 – Acesso relacionado a rotina, se esta posição não for informada
não validará os acessos.
Ex e m p l o
Funções
AllGroups
Retorna vetor contendo informações dos grupos de usuários.
Si n t a x e
D es c r i ç ã o
A função AllGroups() retorna um vetor principal onde cada elemento refere-se a um grupo de usuários
do sistema, estes elementos são compostos de um vetor multidimensional subdividindo as
informações dos grupos. Sua estrutura é composta de:
1 ID C 6
2 Nome C 20
4 Data de validade D 8
330
7 Idioma N 1
8 Diretório C 100
9 Impressora C
10 Acessos C 512
13 Tipo de impressão N 1
14 Formato N 1
15 Ambiente N 1
16 Opção de impressão L 1
Ex e m p l o
Local aGrupos:= {}
aGrupos:= ALLGROUPS()
AllUsers
Retorna vetor contendo informações dos usuários do sistema.
Si n t a x e
D es c r i ç ã o
A função AllUsers() retorna um vetor principal onde cada elemento refere-se a um usuário do sistema,
estes elementos são compostos de um vetor multidimensional subdividindo as informações dos
usuários. Sua estrutura é composta de:
331
1 ID C 6
2 Nome C 15
3 Senha C 6
4 Nome Completo C 30
6 Data de validade D 8
11 ID do superior C 6
12 Departamento C 30
13 Cargo C 30
14 E-Mail C 130
15 Número de acessos simultâneos N 4
16 Data da última alteração D 8
17 Usuário bloqueado L 1
18 Número de dígitos para o ano N 1
19 Listner de ligações L 1
20 Ramal C 4
2
1 Vetor com horários de acesso A --
2 Idioma N 1
3 Diretório C 100
4 Impressora C --
5 Acessos C 512
6 Vetor com empresas A --
7 Ponto de entrada C 10
8 Tipo de impressão N 1
9 Formato N 1
10 Ambiente N 1
11 Prioridade p/ config. do grupo L 1
12 Opção de impressão C 50
13 Acesso a outros dir de impressão L 1
3
1 Módulo+nível+menu C
332
Ex e m p l o
Local aUsuario:= {}
aUsuario:= ALLUSERS()
APMsgAler t
Exibe uma mensagem em um diálogo
Si n t a x e
D es c r i ç ã o
Esta função exibe uma mensagem em um diálogo para alertar o usuário com um botão para confirmar e
um ícone de mensagem de aviso.
Ex e m p l o
APMSGALERT(“Atenção”)
APMsg I nfo
Exibe uma mensagem em um diálogo
Si n t a x e
D es c r i ç ã o
Esta função exibe uma mensagem em um diálogo para alertar o usuário com um botão para confirmar e
um ícone de mensagem de aviso.
333
Ex e m p l o
APMSGINFO(“Atenção”)
APMsgNoYes
Exibe uma mensagem em um diálogo
Si n t a x e
D es c r i ç ã o
Esta função exibe uma mensagem em um diálogo para o usuário com um botão para confirmar e um para
cancelar. Caso cancele a função retornará verdadeiro, senão retornará falso.
Ex e m p l o
If !APMSGNOYES(“Abandonar?”)
Return
EndIf
APMsgSt op
Exibe uma mensagem em um diálogo
Si n t a x e
D es c r i ç ã o
Esta função exibe uma mensagem em um diálogo para alertar o usuário com um botão para confirmar e
um ícone de mensagem crítica.
334
Ex e m p l o
APMSGSTOP(“Atenção”)
APMsgYesNo
Exibe uma mensagem em um diálogo
Si n t a x e
D es c r i ç ã o
Esta função exibe uma mensagem em um diálogo para o usuário com um botão para confirmar e um para
cancelar. Caso confirme a função retornará verdadeiro, senão retornará falso.
Ex e m p l o
If APMSGYESNO(“Abandonar ?”)
Return
EndIf
APMsgYesNo
Exibe uma mensagem em um diálogo
Si n t a x e
D es c r i ç ã o
Esta função exibe uma mensagem em um diálogo para o usuário com um botão para confirmar e um para
cancelar. Caso confirme a função retornará verdadeiro, senão retornará falso.
335
Ex e m p l o
If APMSGYESNO(“Abandonar ?”)
Return
EndIf
Cabec
Imprime cabeçalho personalizado nos relatórios.
Si n t a x e
CABEC( cTit ulo, cCabec1 , cCabec2 , cProg ra ma, cTamanho, [ nFor mato ], [ uPar ], [ lPerg ] ) -> nil
D es c r i ç ã o
A função Cabec() imprime o cabeçalho personalizado de acordo com o conteúdo dos parâmetros cCabec1
e cCabec2. O logo impresso no cabeçalho é uma imagem de extensão “.bmp”, cujo nome está associado
com o empresa corrente. Ex: ‘LGRL01.BMP’, ‘01’ é a empresa.
Ex e m p l o
336
wrel := SetPrint( cAlias, cProgram, cPerg, @cTitulo, cDesc1, cDesc2, cDesc3, lDic, aOrd ,
lCompres, cTam )
If nLastKey == 27
Set Filter To
Return
EndIf
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SetRegua( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
CABEC( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin,000 PSAY __PrtThinLine()
IncRegua()
dbSkip()
End
IF nLin != 80
nLin++
If nLin > 60
CABEC( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
Endif
337
Set Printer TO
dbCommitAll()
OurSpool( wrel )
Endif
MS_FLUSH()
Return
Capi tal
Corrige maiúsculas e minúsculas de uma frase.
Si n t a x e
D es c r i ç ã o
Esta função coloca a primeira letra de cada palavra em maiúscula e o restante em minúscula em toda a
frase.
Ex e m p l o
CloseBro wse
Fecha a MBrowse ou a MarkBrow.
Si n t a x e
D es c r i ç ã o
338
Conpad1
Exibe a tela de consulta padrão.
Si n t a x e
CONPAD1( [ uPar1 ], [ uPar2 ], [ uPar3 ], cAlias, [ cCa mpoRe t ], [ uPar4 ], [ lVisual ] ) -> lógico
cCampoRet Não C Nome da variável ou campo que receberá o retorno da consulta padrão.
D es c r i ç ã o
Esta função exibe a tela de consulta padrão baseada no Dicionário de Dados (SXB).
Ex e m p l o
CONPAD1(,,,”SA1”,,,.F.)
Enchoicebar
Cria barra de botões padrão na janela
Si n t a x e
339
D es c r i ç ã o
Esta função cria uma barra com botões padrão e outros passados como parâmetro na janela tambem
passada por parâmetro. A EnchoiceBar dever ser chamada antes do ACTIVATE da janela.
Ex e m p l o
FileNoEx t
Retorna o nome de um arquivo sem a extensão.
Si n t a x e
D es c r i ç ã o
A função FileNoExt() retorna o nome de um arquivo contido em uma string, ignorando a extensão.
Ex e m p l o
340
Final
Utilizada para finalizar o sistema.
Si n t a x e
Argu m en t o Ob r i g a t . Ti p o D e sc r i ç ã o
D es c r i ç ã o
Esta função executa operações básicas que garantem a integridade dos dados ao finalizar o sistema
desmontando as transações (se houver), desbloqueando os semáforos e fechando as tabelas abertas.
Ex e m p l o
FTPConnect
Cria conexão com servidor FTP.
Si n t a x e
D es c r i ç ã o
A função FTPConnect() retorna verdadeiro se a operação for realizada com sucesso. Se existir uma
conexão ativa e for solicitada uma nova, retornará falso.
341
A rg u m en to Ob r i g a t . Ti p o D es c r iç ã o
Ex e m p l o
Local cServidor
Local cCurDir
cServidor := 'ftp.caminhodoservidor.com.br'
If !FTPCONNECT( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
FTPDirChange
Altera o diretório corrente do FTP.
Si n t a x e
D es c r i ç ã o
A função FTPDirChange () retornará verdadeiro (.T.) se a operação for realizada com sucesso.
Ex e m p l o
Local cServidor
Local aArqs
Local aDirs
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
If FTPDirChange('diretorio')
aDirs := FTPDirectory( '*.*', 'D' )
aArqs := FTPDirectory( '*.*' )
342
EndIf
FTPDirectory
Cria um vetor com informações de diretórios e arquivos do FTP.
Si n t a x e
D es c r i ç ã o
A função FTPDirectory() retorna um vetor contendo informações dos diretórios e arquivos contidos no FTP.
Ex e m p l o
Local cServidor
Local aArqs
Local aDirs
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
If FTPDirChange('diretorio')
aDirs := FTPDIRECTORY( '*.*', 'D' )
aArqs := FTPDIRECTORY( '*.*' )
EndIf
FTPDisconnect
Elimina conexão atual.
Si n t a x e
D es c r i ç ã o
A função FTPDisconnect() retornará verdadeiro (.T.) se a operação for realizada com sucesso. Se não
existir uma conexão a função retornará falso (.F.). Se a operação for realizada com sucesso a função
retorna verdadeiro (.T.).
343
Ex e m p l o
Local cServidor
Local aArqs
Local aDirs
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDISCONNECT()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
FTPDirChange ('diretorio')
aDirs := FTPDirectory( '*.*', 'D' )
aArqs := FTPDirectory( '*.*' )
FTPDo w nload
Copia um arquivo no servidor FTP para o servidor local.
Si n t a x e
D es c r i ç ã o
A função FTPDownload() copia um arquivo no servidor FTP para uma máquina local em um diretório
(informado no parâmetro cArqDest) abaixo do RootPath do Protheus.
Ex e m p l o
Local cServidor
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
If FTPDirChange('diretorio')
If !FTPDOWNLOAD( '\DIRETORIO\ARQ00001.ARQ', 'ARQ00001.ARQ' )
APMsgInfo( 'Problemas ao copiar arquivo!' )
EndIf
EndIf
FTPErase
Apaga arquivo no servidor FTP.
344
Si n t a x e
D es c r i ç ã o
A função FTPErase() apaga arquivo no diretório corrente do FTP. Se a operação for realizada com sucesso
a função retornará verdadeiro (.T.).
Ex e m p l o
Local cServidor
Local aArqs
Local aDirs
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
If FTPDirChange('diretorio')
If !FTPERASE( ‘Arquivo.ext’ )
APMsgInfo(‘Problemas ao apagar o arquivo!’ )
EndIf
EndIf
FTPGetCurDir
Retorna o diretório corrente no FTP.
Si n t a x e
Ex e m p l o
Local cServidor
Local cCurDir
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
cCurDir := FTPGETCURDIR()
FTPRenameFile
345
Si n t a x e
D es c r i ç ã o
A função FTPRenameFile() renomeia um arquivo no diretório corrente do servidor FTP. Se a operação for
realizada com sucesso a função retornará verdadeiro (.T.).
Ex e m p l o
Local cServidor
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
If FTPDirChange('diretorio')
If !FTPRENAMEF I LE ( 'ARQ00001.ARQ', 'ARQ00002.ARQ' )
APMsgInfo( 'Problemas ao renomear arquivo!' )
EndIf
EndIf
FTPUpload
Copia um arquivo na máquina local para o servidor FTP.
Si n t a x e
D es c r i ç ã o
346
A função FTPUpload() copia um arquivo na máquina local para o diretório corrente no servidor FTP. O
arquivo a ser copiado deve estar abaixo do RootPath do Protheus. Se a operação for realizada com
sucesso a função retornará verdadeiro (.T.).
Ex e m p l o
Local cServidor
cServidor := 'ftp.caminhodoserivor.com.br'
FTPDisconnect()
If !FTPConnect( cServidor )
APMsgInfo( 'Falha na conexão!' )
EndIf
If FTPDirChange('diretorio')
If !FTPUPLOAD( '\DIRETORIO\ARQ00001.ARQ', 'ARQ00001.ARQ' )
APMsgInfo( 'Problemas ao copiar arquivo!' )
EndIf
EndIf
FunDesc
Retorna descrição de uma opção do menu.
Si n t a x e
D es c r i ç ã o
Ex e m p l o
Local cDescr
cDescr := FUNDESC()
FunName
Retorna nome de uma função do menu.
Si n t a x e
D es c r i ç ã o
A função FunName() retornará o nome de uma função executada a partir de um menu do Siga
Ex e m p l o
Local cFunction
cFunction := FUNNAME()
347
GetCoun t ryList
Retorna vetor contendo informações dos países localizados.
Si n t a x e
D es c r i ç ã o
O vetor retornado possui três dimensões, a primeira refere-se a sigla dos países, o segundo ao nome do
país e o terceiro a identificação do país com dois dígitos.
Ex e m p l o
Get Mar k
Retorna string de caracteres aleatórios.
Si n t a x e
D es c r i ç ã o
A GetMark() é utilizada junto a função MarkBrow() onde são utilizados combinações de caracteres para
controle de marcas.
Ex e m p l o
Function <nome-da-função>( )
Local aCampos := {{'CB_OK' ,,''},;
{'CB_USERLIB' ,,'Usuário'},;
348
{'CB_TABHORA' ,,'Hora'},;
{'CB_DTTAB' ,,'Data'}}
Private cMarca := GETMARK()
Private cCadastro := 'Cadastro de Contrato'
Private aRotina := { { 'Pesquisar' , 'AxPesqui' , 0, 1 }}
MarkBrow( 'SCB', 'CB_OK','!CB_USERLIB',aCampos,, cMarca,'MarkAll()',,,,'Mark()' )
Return
GetMv
Retorna o conteúdo de um parâmetro cadastrado no SX6.
Si n t a x e
D es c r i ç ã o
Se lPar02 for passado como .T. ( Verdadeiro ), o retorno da função será um valor lógico indicando se o
parâmetro existe.
Quando uPar03 for informado, caso o parâmetro informado em cPar01 não exista, o retorno da função
será o valor informado em uPar03 caso contrário retorna o conteúdo do parâmetro. Se uPar03 for
informado o conteúdo de lPar02 será desconsiderado.
Ex e m p l o
349
I ncProc
Incrementa régua de progressão.
Si n t a x e
D es c r i ç ã o
Para incrementar a régua criada pela função Processa(), utilizamos a função IncProc()
Ex e m p l o
I ncRegua
Incrementa valores na régua de progressão criada pela função RptStatus().
Si n t a x e
D es c r i ç ã o
Após executar as funções RptStatus() e SetRegua(), para incrementar valores na régua utilizamos a
função IncRegua().
Ex e m p l o
350
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SetRegua( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin,000 PSAY __PrtThinLine()
INCREGUA()
dbSkip()
End
IF nLin != 80
nLin++
If nLin > 60
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
Endif
@ nLin,000 PSAY __PrtThinLine()
Roda( 0, cTitulo, cTamanho ) // Rodapé
EndIf
If aReturn[5] = 1
Set PrinterTO
dbCommitAll()
OurSpool( wrel )
Endif
MS_FLUSH()
351
Return
I ndRegua
Cria índice temporário com expressão de filtro.
Si n t a x e
INDREGUA( cAlias, cIndice, cEx press, [ xOrde m] , [ cFor ], [ cMens ], [ lEx ibir ] ) -> nil
D es c r i ç ã o
Esta função cria um índice temporário para o alias especificado podendo ou não ter um filtro e tambem
podendo ser decrescente se o parâmetro xOrdem for especificado como “D”. Durante a criação do índice
um diálogo com uma barra de progressão será criada podendo esta ser omitida.
Ex e m p l o
352
FErase(cArquivo+OrdBagExt())
Return
Mar kBRefresh
Atualiza a MarkBrow.
Si n t a x e
D es c r i ç ã o
Mar kBro w
Monta um Browse onde as linhas podem ser marcadas ou desmarcadas.
Si n t a x e
MARKBROW( cAlias, cCa mpo, [ cCpo ], [ aCam pos ], [ l Inver te ], cMarca, [ cCt rlM ], [ uPar ], [
cExp Ini ], [ cExpFi m ], [ cAval ] ) -> nil
cCampo Sim C Campo do arquivo onde será feito o controle (gravação) da marca.
cCtrlM Não C Função a ser executada caso deseje marcar todos elementos.
353
D es c r i ç ã o
As variáveis cCadastro e aRotina (*) precisam ser declarados como private acima da chamada da função.
O vetor informado no parâmetro aCampos deve conter as seguintes dimensões: 1º – nome do campo; 2º
- Nada (Nil); 3º - Título do campo; 4º - Máscara (picture).
(*) vetor com as rotinas que serão executadas, nele será definido o tipo de operação a ser executada
(inclusão, alteração, exclusão, visualização, pesquisa, ...) sua estrutura é composta de 5 (cinco)
dimensões: 1º - Título; 2º – Rotina; 3º – Reservado; 4º – Operação (1 - pesquisa; 2 - visualização; 3 -
inclusão; 4 - alteração; 5 - exclusão); 5 – Acesso relacionado a rotina, se esta posição não for informada
nenhum acesso será validado.
Ex e m p l o
Function <nome-da-função>( )
Local aCampos := { {'CB_OK' ,,''},;
{'CB_USERLIB' ,,'Usuário'},;
{'CB_TABHORA' ,,'Hora'},;
{'CB_DTTAB' ,,'Data'}}
Private cMarca := GetMark()
Private cCadastro := 'Cadastro de Contrato'
Private aRotina := { { 'Pesquisar' , 'AxPesqui' , 0, 1 }}
MARKBROW( 'SCB', 'CB_OK','!CB_USERLIB',aCampos,, cMarca,'MarkAll()',,,,'Mark()' )
Return
Ms_Flush
Descarrega spool de impressão.
354
Si n t a x e
D es c r i ç ã o
Após os comandos de impressão as informações ficam armazenadas no spool e são descarrega em seus
destinos através da função Ms_Flush().
Exe m plo
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SetRegua( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin,000 PSAY __PrtThinLine()
IncRegua ()
dbSkip()
End
IF nLin != 80
355
nLin++
If nLin > 60
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
Endif
@ nLin,000 PSAY __PrtThinLine()
Roda( 0, cTitulo, cTamanho ) // Rodapé
EndIf
If aReturn[5] = 1
Set PrinterTO
dbCommitAll()
OurSpool( wrel )
Endif
MS_FLUSH ()
Return
MsAppend
Adiciona registros de um arquivo para outro.
Si n t a x e
D es c r i ç ã o
A função MsAppend() adiciona registros de um arquivo para outro, respeitando a estrutura das tabelas. Se
a operação for realizada com sucesso o função retornará verdadeiro (.T.).
Ex e m p l o
dbSelectArea(‘XXX’)
MSAPPEND(,‘ARQ00001’)
MsCopyFile
Executa copia binária de um arquivo.
Si n t a x e
356
D es c r i ç ã o
Ex e m p l o
MsCopyTo
Realiza copia de um arquivo de dados.
Si n t a x e
D es c r i ç ã o
A função MsCopyTo() copia os registros de uma base de dados para outra, criando o arquivo destino de
acordo com a estrutura da base de dados origem.
Ex e m p l o
357
MsCreate
Cria arquivo de dados.
Si n t a x e
D es c r i ç ã o
A função MsCreate() cria um arquivo (tabela) de acordo com a estrutura informada no parâmetro aStrut
(*). Se o parâmetro cDriver não for informado o RDD corrente será assumido como padrão. Para criação
de tabelas no TopConnect é necessário estar conectado ao banco e o environment do Protheus ser TOP.
(*) vetor contendo a estrutura da tabela: 1º - caracter, nome do campo; 2º - caracter, tipo do campo; 3º
- numérico, tamanho do campo; 4º - numérico, decimais.
Ex e m p l o
MsErase
Deleta arquivo.
Si n t a x e
358
D es c r i ç ã o
A função MsErase() retornará verdadeiro (.T.) se a operação for realizada com sucesso.
Ex e m p l o
MsFile
Verifica existência de um arquivo.
Si n t a x e
D es c r i ç ã o
A função MsFile() retornará verdadeiro (.T.) se a operação for realizada com sucesso.
Ex e m p l o
359
MsRename
Renomeia arquivo de acordo com RDD corrente.
Si n t a x e
D es c r i ç ã o
Ex e m p l o
MsUnlock
Libera lock de registro.
Si n t a x e
D es c r i ç ã o
Ex e m p l o
360
OurSpool
Gerenciador de impressão.
Si n t a x e
D es c r i ç ã o
Ex e m p l o
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
361
Pergun te
Inicializa as variáveis de pergunta (mv_par??).
Si n t a x e
D es c r i ç ã o
362
para edição da pergunta e se o usuário confirmar as variáveis serão atualizadas e a pergunta no SX1
também será atualizada.
Ex e m p l o
PERGUNTE(“CON010”)
Processa
Cria diálogo com uma régua de progressão.
Si n t a x e
D es c r i ç ã o
A função Processa() cria um diálogo onde a execução de um determinada função pode ser acompanhada
através de uma régua de progressão. Para atribuir o valor total da régua utilizamos a função ProcRegua()
e para incrementar a régua utilizamos a função IncProc().
Exe m plo
363
Return
ProcRegua
Atribui o valor total da régua de progressão cria pela pela função Processa().
Si n t a x e
D es c r i ç ã o
Após atribuir o valor total da régua, para incrementar utilizamos a função IncProc().
Exe m plo
PswAdmin
Verifica se um usuário pertence ao grupo de administradores.
Si n t a x e
364
D es c r i ç ã o
A função PswAdmin() retorna 0 (zero) se o usuário for do grupo de administradores, 1 (um) para usuário
não administrador e 2 (dois) se for senha inválida.
Ex e m p l o
Psw I D
Retorna o ID do usuário ou do grupo de usuário.
Si n t a x e
D es c r i ç ã o
Utilizada para retornar o ID do usuário ou do grupo de usuários após ter posicionado o arquivo de senha
com a função PswSeek().
Ex e m p l o
Ps wName
Verifica senha de usuário.
Si n t a x e
365
D es c r i ç ã o
A função PswName() verifica se a senha informada no parâmetro cSenha pertence ao usuário posicionado
no arquivo de senha, se pertencer retornará verdadeiro(.T.).
Ex e m p l o
Ps wOrder
Posiciona a ordem de indexação do arquivo de senhas.
Si n t a x e
D es c r i ç ã o
A função PswOrder() posiciona a ordem de indexação de acordo com o parametro nOrdem, onde:
1 – ID;
2 – usuário;
3 – senha;e
4 – e-mail.
Ex e m p l o
366
PswRet
Retorna vetor contendo informações do Usuário ou do Grupo de Usuários.
Si n t a x e
D es c r i ç ã o
A função PswRet() retorna dois tipos de vetores distintos, de acordo com o posicionamento do arquivo de
senha. Se no segundo parâmetro da função PswSeek() for informado .T. a PswRet() retornará um vetor
com informações do Usuários, caso contrário retornará informações do Grupo de Usuários.
Ex e m p l o
// Exemplo 1
User Function <nome-da-função>( cUsuario )
Local aArray := {}
PswOrder(2)
If PswSeek( cUsuario, .T. )
aArray := PSWRET() // Retorna vetor com informações do usuário
EndIf
Return
// Exemplo 2
User Function <nome-da-função>( cGrupoID )
Local cGrupo
PswOrder(1)
If PswSeek( cGrupoId, .F. )
cGrupo := PSWRET()[1][2] // Retorna nome do Grupo de Usuário
EndIf
Return
PswSeek
Pesquisa e posiciona o arquivo de senhas.
Si n t a x e
lUsuario Não L
Se verdadeiro (.T.) pesquisa por usuários, se falso (.F.) pesquisa por
grupo de usuários. O valor assumido como padrão é .T.
367
D es c r i ç ã o
Ex e m p l o
ReadVar
Retorna o nome da variável que esta sendo editada.
Si n t a x e
D es c r i ç ã o
Retorna o nome da variável que esta sendo editada pela MsGetDados, MsGetDB e MsMGet (Enchoice) para
ser usada na validação de um campo por exemplo.
Ex e m p l o
cVar := READVAR()
If Type(cVar) == “C”
APMsgInfo(“Opção escolhida: ”+&cVar)
EndIf
RetAcsName
Retorna a extensão do arquivo de acessos corrente.
Si n t a x e
D es c r i ç ã o
A função RetAscName retorna a extensão do arquivo de acessos de acordo com idioma corrente.
368
Ex e m p l o
Local cExt
cExt := RETACSNAME()
If ‘ACS’ $ cExt
APMsgInfo( ‘Menu Português’ )
ElseIf ‘ACE’ $ cExt
APMsgInfo( ‘Menu Espanhol' )
ElseIf ‘ACI’ $ cExt
APMsgInfo( ‘Menu Inglês’ )
EndIf
RetEx tHlp
Retorna a extensão do help de campo.
Si n t a x e
D es c r i ç ã o
Esta função retorna uma string contendo a extensão do help de campos de acordo com idioma corrente.
Ex e m p l o
Local cExt
cExt := RETEXTHLP()
If ‘HLP’ $ cExt
APMsgInfo( ‘Help de Campos em Português’ )
ElseIf ‘HLE’ $ cExt
APMsgInfo( ‘Help de Campos em Espanhol' )
ElseIf ‘HLI’ $ cExt
APMsgInfo( ‘Help de Campos em Inglês’ )
EndIf
RetEx tHls
Retorna a extensão do help de soluções.
Si n t a x e
D es c r i ç ã o
Esta função retorna uma string contendo a extensão do help de soluções de acordo com idioma corrente.
Ex e m p l o
Local cExt
369
cExt := RETEXTHLS()
If ‘HLS’ $ cExt
APMsgInfo( ‘Help de Soluções em Português’ )
ElseIf ‘HSE’ $ cExt
APMsgInfo( ‘Help de Soluções em Espanhol' )
ElseIf ‘HSI’ $ cExt
APMsgInfo( ‘Help de Soluções em Inglês’ )
EndIf
RetEx tHpr
Retorna a extensão do help do programa.
Si n t a x e
D es c r i ç ã o
Esta função retorna uma string contendo a extensão do help de programas de acordo com idioma
corrente.
Ex e m p l o
Local cExt
cExt := RETEXTHPR()
If ‘HPR’ $ cExt
APMsgInfo( ‘Help de Programas em Português’ )
ElseIf ‘HPE’ $ cExt
APMsgInfo( ‘Help de Programas em Espanhol' )
ElseIf ‘HPI’ $ cExt
APMsgInfo( ‘Help de Programas em Inglês’ )
EndIf
RetEx tMnu
Retorna a extensão do menu corrente.
Si n t a x e
D es c r i ç ã o
Esta função retorna uma string contendo a extensão do menu de acordo com idioma corrente.
Ex e m p l o
Local cExt
cExt := RETEXTMNU()
If ‘MNU’ $ cExt
370
RetFileName
Retorna o nome de um arquivo sem o caminho e sem a extensão.
Si n t a x e
D es c r i ç ã o
A função RetFileName() retorna o nome de um arquivo contido em uma string, ignorando o caminho e a
extensão.
Ex e m p l o
Roda
Imprime rodapé no relatório.
Si n t a x e
371
Ex e m p l o
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SetRegua( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin,000 PSAY __PrtThinLine()
IncRegua ()
dbSkip()
End
IF nLin != 80
nLin++
If nLin > 60
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
Endif
@ nLin,000 PSAY __PrtThinLine()
RODA( ,, cTamanho ) // Rodapé
EndIf
If aReturn[5] = 1
Set Printer TO
dbCommitAll()
OurSpool( wrel )
372
Endif
MS_FLUSH()
Return
RptStat us
Cria um diálogo com régua de progressão.
Si n t a x e
D es c r i ç ã o
A função RptStatus() exibe um diálogo onde a execução da função de relatório pode ser acompanhada
através de uma régua de progressão. Para controlar a régua utilizamos as funções SetRegua() para
atribuir o valor total da régua, e a função IncRegua() para incrementar. Caso o processamento seja
interrompido através do botão cancelar, um valor lógico é retornado no parâmetro do código de bloco.
Exe m plo
373
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SetRegua( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin,000 PSAY __PrtThinLine()
IncRegua ()
dbSkip()
End
IF nLin != 80
nLin++
If nLin > 60
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
Endif
@ nLin,000 PSAY __PrtThinLine()
Roda( 0, cTitulo, cTamanho ) // Rodapé
EndIf
If aReturn[5] = 1
Set Printer TO
dbCommitAll()
OurSpool( wrel )
Endif
MS_FLUSH()
Return
SetDefault
Prepara ambiente de impressão.
Si n t a x e
SETDEFAULT( aRe tu rno, [ cAlias ], [ uPar1 ], [ uPar2 ], [ cTa manho ], [ nFor ma to ] ) -> nil
Argu mento Ob r i g a t . Ti p o D e sc r i ç ã o
374
D es c r i ç ã o
Após executar a função SetPrint() o vetor aReturn conterá as informações necessárias para que
SetDefault() prepare o ambiente de impressão.
Ex e m p l o
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SetRegua( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
375
SetPrin t
Interface onde são configuradas as opções de impressão.
Si n t a x e
SETPRINT( cAlias, cPrograma, [ cPerg ], [ cTit ulo ], [ cDesc1 ], [ cDesc2 ], [ cDesc3 ], [ lDic ], [ aOrd
], [ lCom pres ], [ cTa m ], [ uPar1 ], lFiltro, [ lCr ystal ], [ cNomeDr v ], [ uPar2 ], [ lSer v idor ], [
cPor taI mpr ] ) -> caracter
376
cNomeDr v Não
C Nome de um driver de impressão.
D es c r i ç ã o
A função SetPrint() cria a interface (diálogo) onde as opções de impressão de um relatório podem ser
configuradas. Basicamente duas variáveis m_pag (*) e aReturn (**) precisam ser declaradas como
privadas (private) antes de executar a SetPrint(). Após confirmada, os dados são armazenados no vetor
aReturn que será passado como parâmetro para função SetDefault().
(**) vetor contendo as opções de impressão, sua estrutura é composta de 8 (oito) elementos: 1º -
caracter, tipo do formulário; 2º - numérico, opção de margem; 3º - caracter, destinatário; 4º - numérico,
formato da impressão; 5º - numérico, dispositivo de impressão; 6º - reservado; 7º - reservado; 8º -
numérico, ordem.
Ex e m p l o
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
377
SetRegua
Atribui valor total da régua de progressão.
Si n t a x e
D es c r i ç ã o
Após executar a função RptStatus() é necessário atribuir o valor total da sua régua, isso será feito através
da função SetRegua().
Ex e m p l o
378
// rotina de impressão
Static Function Imprime( lFim, cAlias, cTitulo, cProgram, cTamanho )
Local nLin := 80
Local cCabec1 := 'Cabecalho 1'
Local cCabec2 := 'Cabecalho 2'
dbSelectArea( cAlias )
SETREGUA( RecCount() )
While !Eof() .And. ( XX_COD >= MV_PAR01 .And. XX_COD <= MV_PAR02 )
If lFim
@Prow()+1,001 PSAY "CANCELADO PELO OPERADOR"
Exit
EndIf
If nLin > 58
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
nLin := 8
EndIf
@ nLin,000 PSAY __PrtFatLine()
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin++,001 PSAY ...
@ nLin,000 PSAY __PrtThinLine()
IncRegua ()
dbSkip()
End
IF nLin != 80
nLin++
If nLin > 60
Cabec( cTitulo, cCabec1, cCabec2, cProgram, cTamanho, 15 ) // cabeçalho
Endif
@ nLin,000 PSAY __PrtThinLine()
Roda( 0, cTitulo, cTamanho ) // Rodapé
EndIf
If aReturn[5] = 1
Set Printer TO
dbCommitAll()
OurSpool( wrel )
Endif
MS_FLUSH()
Return
379
SixDescricao
Retorna descrição de uma chave de índice.
Si n t a x e
D es c r i ç ã o
Esta função retorna a descrição da chave de índice, de acordo com o registro posicionado no SIX e idioma
corrente.
Ex e m p l o
VerSenha
Verifica se o usuário tem acesso a determinada opção.
Si n t a x e
D es c r i ç ã o
Esta função verifica se o usuário corrente tem acesso a determinada opção que foi cadastrada no
Configurador nas propriedades do usuário (“Excluir produto”,”Alterar produto”,...).
Ex e m p l o
380
X1Def01
Retorna o conteúdo da primeira definição da pergunta (caso seja combo).
Si n t a x e
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX1 e o idioma corrente.
Ex e m p l o
X1Def02
Retorna o conteúdo da segunda definição da pergunta (caso seja combo).
Si n t a x e
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX1 e o idioma corrente.
Ex e m p l o
381
Local cDef02
Local cDef03
Local cDef04
Local cDef05
dbSelectArea(“SX1”)
dbSetOrder(1)
If dbSeek( cGrupo + cPerg ) // grupo da pergunta + o numero da perg.
cDef01 := X1Def01()
cDef02 := X1DEF02()
cDef03 := X1Def03()
cDef04 := X1Def04()
cDef05 := X1Def05()
EndIf
Return
X1Def03
Retorna o conteúdo da terceira definição da pergunta (caso seja combo).
Si n t a x e
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX1 e o idioma corrente.
Ex e m p l o
X1Def04
Retorna o conteúdo da quarta definição da pergunta (caso seja combo).
Si n t a x e
382
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX1 e o idioma corrente.
Ex e m p l o
X1Def05
Retorna o conteúdo da quinta definição da pergunta (caso seja combo).
Si n t a x e
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX1 e o idioma corrente.
Ex e m p l o
X1Pergun t
383
Si n t a x e
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX1 e o idioma corrente.
Ex e m p l o
X2Nome
Retorna o descrição de uma tabela contida no dicionário de dados SX2.
Si n t a x e
D es c r i ç ã o
O conteúdo retornado pela função será de acordo com o registro posicionado no SX2 e o idioma corrente.
Ex e m p l o
384
X3CBox
Retorna o conteúdo de um campo tipo combo contido no dicionário de dados SX3
Si n t a x e
D es c r i ç ã o
Esta função retorna conteúdo do campo combo de acordo com o registro posicionado no SX3 e o idioma
corrente.
Ex e m p l o
X3Descric
Retorna o descrição de um campo contido no dicionário de dados SX3
Si n t a x e
D es c r i ç ã o
Esta função retorna a descrição do campo de acordo com o registro posicionando no SX3 e o idioma
corrente.
Ex e m p l o
385
EndIf
Return
X3Pict ure
Retorna a mascara de um campo do dicionário de dados SX3.
Si n t a x e
Ex e m p l o
X3Ti t ulo
Retorna o título de um campo contido no dicionário de dados SX3
Si n t a x e
D es c r i ç ã o
Esta função retorna o título do campo de acordo com o registro posicionado no SX3 e o idioma corrente.
Ex e m p l o
X3Uso
386
Si n t a x e
D es c r i ç ã o
Esta função retornará um valor lógico, se for uma campo usado verdadeiro (.T.), caso contrário falso (.F.).
Ex e m p l o
X5Descri
Retorna a descrição de uma tabela cadastrada no dicionário de dados SX5
Si n t a x e
D es c r i ç ã o
Esta função retorna a descrição da tabela de acordo com o registro posicionado no SX5 e o idioma
corrente.
Ex e m p l o
387
X6Con teud
Retorna o conteúdo do parâmetro cadastrado no dicionário de dados SX6.
Si n t a x e
D es c r i ç ã o
Esta função retorna o conteúdo de um parâmetro de acordo com o registro posicionado no SX6 e idioma
corrente.
Ex e m p l o
X6Desc1
Retorna o primeiro complemento da descrição de um parâmetro cadastrado no dicionário de dados SX6.
Si n t a x e
D es c r i ç ã o
Esta função retorna o conteúdo do primeiro complemento da descrição de um parametro de acordo com o
registro posicionado no SX6 e o idioma corrente.
Ex e m p l o
388
dbSelectArea(“SX6”)
dbSetOrder(1)
If dbSeek( cFilial+cParm )
cDescr := X6Descric()
cDescr += X6DESC1()
cDescr += X6Desc2()
cConteud := X6Conteud()
EndIf
Return
X6Desc2
Retorna o segundo complemento da descrição de um parâmetro cadastrado no dicionário de dados SX6.
Si n t a x e
D es c r i ç ã o
Esta função retorna o conteúdo do segundo complemento da descrição de um parâmetro de acordo com o
registro posicionado no SX6 e o idioma corrente.
Ex e m p l o
X6Descric
Retorna a descrição de um parâmetro cadastrado no dicionário de dados SX6.
Si n t a x e
D es c r i ç ã o
Esta função retorna o conteúdo da descrição de um parâmetro de acordo com o registro posicionado no
SX6 e o idioma corrente.
Ex e m p l o
389
XADescric
Retorna a descrição dos folders (pastas) cadastrados no dicionário de dados SXA.
Si n t a x e
D es c r i ç ã o
Esta função retorna o conteúdo da descrição dos folders de acordo com o registro posicionado no SXA e o
idioma corrente.
Ex e m p l o
XBDescri
Retorna descrição de uma consulta SXB.
Si n t a x e
D es c r i ç ã o
Esta função retorna o conteúdo da descrição de uma consulta de acordo com o registro posicionado no
SXB e o idioma corrente.
390
Ex e m p l o
3-Remova o serviço do AP6 Server chamado pelo iniciar / executar o AP6SVR com a cláusula
"-remove"
[Service]
name=AP5
Displayname=AP5
[Service]
name=AP6
Displayname=AP6
391
Se subir legal os dois, confirme pelo service do Win2000 que ambos estão no ar, startados e como
automáticos.
Se não der certo, volte à situação original, ou seja, AP6SVR automático como serviço e AP5SVR como
console.
Através do Office Kit, encontrado no CD de instalação da versão 407 em diante, o Siga oferece
integração com os aplicativos do pacote Office da Microsoft. É importante lembrar que o S i g a A d v a n c e d
p o ss u í i n t e g r a ç ã o s o m e n t e c o m o Ex c e l e que a integração com o Word está disponível somente para o
módulo de Controle de Documentos do Siga Quality Celerina.
I nstalação
Para instalar o SIGA Advanced for Windows com Microsoft Excel, o usuário deve possuir:
➘ H a r d w a r e – Co n f i g u r aç ã o m í n i m a: Pentium 133 com 16 MB RAM, recomendado Pentium 166 com 32
MB RAM.
➘ M i c r o s o f t Ex c e l – A versão mínima é 7.0 (95), recomendado o uso da versão 8.0 (97)
1. Ex ec u t e o p r o g r a m a d e i n s t a la ç ã o d o S I GA A d v a n c e d .
2. I n s t a l e o S I GA O f f i c e K i t n as e s t aç õ e s.
Observações
1. A instalação do Office Kit deve ser feita em todas as estações que irão utilizar a integração.
2. A MICROSIGA envia dois arquivos exemplos de Planilha Excel, ADVDEMO e ADVDEMO7, para
serem utilizados nas versões Excel 97 e Excel 95, respectivamente. Estes arquivos são
instalados no diretório X:\Arquivos de Programa \ SIGA Advanced Office Kit \ Samples (onde
X: é drive onde está instalado o SIGA Advanced).
Ut ilizando a I n tegração
Pode-se acessar o Microsoft Excel a partir de qualquer Módulo SIGA Advanced, com exceção do SIGACFG
(Configurador ).
392
OBS : A integração somente funcionará se o Excel for aberto a partir do Siga Advanced.
Existem 4 formas de se utilizar as funções do SIGA Advanced em uma planilha Excel. Veja a seguir:
1. Este procedimento é recomendado para usuários menos experientes, pois o Microsoft Excel abre uma
janela assistente para que sejam informados os parâmetros, facilitando o uso de referência a outras
células.
• Clique na célula que deve receber o resultado da função SIGA Advanced e selecione a opção "Funções"
no menu Inserir.
• No lado esquerdo da janela são relacionadas as categorias de funções disponíveis. Selecione a categoria
de funções "D e f i n i d as p e l o u s u á r i o".
• Na caixa de listagem “Nome da Função” , selecione a função que será utilizada. Será apresentada uma
janela Assistente, onde devem ser informados os parâmetros da função, conforme solicitado e definido
pela sua sintaxe.
• Informe os parâmetros da função e clique no botão "OK" para finalizar.
2. Outra forma de se utilizar as funções SIGA, é digitando a função diretamente na célula. Esta forma não
conta com o assistente, e portanto, o usuário deve conhecer a sintaxe da função para informar
corretamente seus parâmetros (recomendada apenas para usuários mais experientes). Para a
informação de uma fórmula no Excel, deve-se digitar o sinal de igual “=”.
3. A terceira forma é utilizar a função SIGA( ) para identificar o início da informação de funções SIGA
Advanced. Para tanto, deve ser usada a seguinte sintaxe:
S I GA ( " n o m e d a f u n ç ã o " ; 1 º p a r â m e t r o d a f u n ç ã o ; 2 º p a r â m e t r o d a f u n ç ã o ; ... )
Por exemplo, informando:
= S I GA ( " MesEx t e n s o " ; 2 ) Desta forma, será retornado o mês “Fevereiro”.
Observe que o nome da função SIGA Advanced é informado entre aspas. (" ").
4. A quarta forma, também é iniciar a informação com a função Siga( ), porém as funções SIGA Advanced,
juntamente com seus parâmetros, devem ser digitados entre aspas, obedecendo a sintaxe padrão que
utiliza os sinais de parênteses. Por exemplo:
= S I GA ( “ MesEx t e n s o ( 2 ) ” )
O Microsoft Excel utiliza um padrão de data diferente do SIGA Advanced, por esse motivo qualquer função
de planilha do Advanced utilizada a partir do menu “Inserir Fórmula” do Microsoft Excel ou da sintaxe
=Siga(“nomefunção”; Par01;Par02) que utilize data como parâmetro ou retorne uma data, deve obedecer as
regras abaixo:
Toda função do SIGA Advanced utilizada a partir do menu “Inserir Fórmula” do Microsoft Excel ou da sintaxe
“=Siga(“nomefunção”;Par01;Par02)” que utiliza valor lógico (.T./.F.) como parâmetro, deve obedecer o
padrão do Microsoft Excel (atenção! com o idioma do Microsoft Excel):
➘ .T. - VERDADEIRO/TRUE
➘ .F. - FALSO/FALSE
Se ao executar uma função SIGA Advanced, o Excel retornar o erro "#VALOR" ou a mensagem “As funções
do SIGA Advanced não constam na lista de funções definidas pelo usuário”, verifique os seguintes tópicos
para solucionar:
➘ Tenha certeza de que o Excel foi iniciado a partir do SIGA Advanced.
393
➘ Através da opção "Suplementos" do Menu "Ferramentas" do Excel, utilize o botão "Procurar" para
localizar o "Add In" do SIGA Advanced (AdvXla80.XLA para a versão 8.0 ou AdvXla para versão 7.0 do
Excel, que estão no diretório de Bibliotecas do Office).
ExecBlocks
Pode-se utilizar Execblock nas células do Microsoft Excel com algumas restrições:
➘ Não devem ser utilizadas entradas de dados ou qualquer outro tipo de “Tela”.
➘ O Execblock deve obrigatoriamente retornar um valor.
➘ O Execblock deve ser pequeno para evitar a perda da conexão do SIGA Advanced com o Microsoft Excel.
➘ A variável que recebe o parâmetro passado pelo Excel é sempre a PARAMIXB, que deve ser tratada
dentro do execblock. Caso seja necessário utilizar mais de um parâmetro no programa, ele já deve vir
do Excel concatenado em uma única String.
➘ Sintaxe: =EXECBLOCK(“Nome da função”,PAR1)
➘ O Rdmake utilizado no ExecBlock deve estar dentro do diretório Sigaadv da base que está sendo
utilizada para chamar o Excel e já estar compilado.
POSICIONE
Posiciona o arquivo em um determinado registro.
Sintaxe: Posicione(ExpC1, ExpN1, ExpC2, ExpC3)
394
onde:
ExpC1 - Alias do arquivo
ExpN1 - Ordem utilizada
ExpC2 - Chave pesquisa
ExpC3 - Campo a ser retornado
Ex.: Posicione(“SA1”,1,xFilial(“SA1”)+001,“A1_NOME”)
MEDIA
Calcula a taxa média de uma determinada moeda em um mês específico.
Sintaxe: Media (ExpN1, ExpN2, ExpN3)
onde:
ExpN1 - Moeda a ser calculada a média
ExpN2 - Mês a ser calculado
ExpN3 - Ano a ser calculado
Ex.:
Media (2,10,94)
Caso o mês e o ano não sejam passados como parâmetros serão assumidos o mês
e ano da database.
SOMAR
Faz o somatório de um arquivo, retornando o valor acumulado de um campo
determinado.
Sintaxe: Somar(ExpC1, ExpC2, ExpC3)
onde:
ExpC1 - Alias do arquivo
ExpC2 - Condição para soma
ExpC3 - Campo a ser somado
Ex.:
Somar(“SI1”",“I1_CLASSE='S' ”,“I1_SALANT”)
Caso o usuário não deseje definir nenhuma condição, a ExpC2 deve ser “.T.”.
GRUPO
Retorna o somatório das células pertencentes a um determinado grupo.
Sintaxe: Grupo(ExpC1)
onde:
ExpC1 - Grupo a ser somado
Ex.: Grupo(1)
CONTAR
Conta o número de registros de acordo com a condição determinada.
Sintaxe: Contar(ExpC1, ExpC2)
onde:
ExpC1 - Alias do arquivo
ExpC2 - Condição para a contagem
Ex:
Contar(“SC1”,“C1_DATPRF < dDataBase”)
SALDO
Devolve o saldo de uma determinada conta.
Sintaxe: Saldo(ExpC1, ExpN1,ExpN2)
onde:
ExpC1 - Código da Conta
ExpN1 - Período do saldo desejado
ExpN2 - Moeda desejada para obtenção do saldo.
Ex.: Saldo(“11101”,12,1)
MOVIMENTO
395
DEBITO
Devolve o valor a débito de uma determinada conta.
Sintaxe: Debito(ExpC1, ExpN1, ExpN2)
onde:
ExpC1 - Código da Conta
ExpN! - Mês do movimento desejado
ExpN2 - Moeda desejada para obtenção do valor a débito
Ex.: Debito(“11103”,03,1)
CREDITO
Devolve o valor a crédito de uma conta.
Sintaxe: Credito(ExpC1, ExpN1, ExpN2)
onde:
ExpC1 - Código da Conta
ExpN1 - Mês do movimento desejado
ExpN2 - Moeda desejada para obtenção do valor a crédito
Ex.: Credito(“11103”,03,1)
SOMAMOVIM
Retorna o movimento dentro de um intervalo de contas analíticas
Sintaxe: SomaMovim(ExpC1, ExpC2, ExpN1, ExpN2)
onde:
ExpC1 - Código da conta De
ExpC2 - Código da conta Até
ExpN1 - Referente ao mês
Exp N2 - Moeda desejada para obtenção do valor
Ex.: SomaMovim(“41304”,“41305”,12,1)
SOMASALDO
Retorna o saldo atual entre um intervalo de contas.
Sintaxe SomaSaldo(ExpC1, ExpC2, ExpN1, ExpN2)
onde:
ExpC1 - Código da conta De
ExpC2 - Código da conta Até
ExpN1 - Referente ao período
ExpN2 - Moeda desejada para obtenção do valor
Ex.: SomaSaldo(“31001”,“31010”,12,1)
ORÇADO
Retorna o valor orçado de uma conta..
Sintaxe Orcado(ExpC1, ExpN1, ExpN2, ExpD1)
onde:
ExpC1 - Código da conta De
ExpN1 - Referente ao período
ExpN2 - Moeda desejada para obtenção do valor
ExpD1 - Data para conversão (em formato data ou caracter), caso não informa-da,
será utilizada a DataBase do sistema.
Ex.: Orcado(“11102001”,1,1)
396
MESEXTENSO
Devolve o nome do mês por extenso.
Sintaxe: MesExtenso(ExpX1)
onde:
ExpX1 - Poderá ser enviado o número de um mês, tanto do tipo caracter como
numérico, ou poderá ser enviada uma data. Caso nada seja informado,
será devolvido o nome do mês referente a Data Base.
Ex.: MesExtenso(01)
VARIAÇÃO
Retorna a variação em percentual entre dois valores.
Sintaxe: Variação(ExpN1, ExpN2)
onde:
ExpN1 - Primeiro fator comparativo
ExpN2 - Segundo fator comparativo
Ex.: Variacao(100000,50000)
MOVIMCC
Retorna o movimento de um centro de custo mais conta contábil (extracontábil).
Sintaxe: MovimCC(ExpC1, ExpC2, ExpN1, ExpN2)
onde:
ExpC1 - Código do centro de custo
ExpC2 - Código da conta contábil
ExpN1 - Referente ao mês
ExpN2 - Moeda desejada para obtenção do valor
Ex.:
MovimCC(“3001”, 111001”,Month(Ddatabase),1)
ORCADOCC
Recupera o valor orçado da Conta x Centro de Custo para utilização na planilha.
Sintaxe: OrcadoCC(ExpC1,ExpC2,ExpN1,ExpN2,ExpD1),
onde:
ExpC1 - Conta
ExpC2 - Centro de Custo
ExpN1 - Período (default mês da database)
ExpN2 - Moeda (default 1)
ExpD1 - Data para conversão se moeda de 2 a 5 - (default dDataBase).
Ex.: OrcadoCC( “111001”,“3001”,3,2)
SUMMOVIMCC
Retorna o movimento de um intervalo de centro de custos extracontábeis. Poderá ser
parametrizados também um grupo de contas.
Sintaxe:
SumMovimCC(ExpC1,ExpC2,ExpC3,ExpC4,ExpN1,ExpN2)
onde:
ExpC1 - do Centro de Custo
ExpC2 - até Centro de Custo
ExpC3 - da Conta
ExpC4 - até a Conta
ExpN1 - Mês (default mês da database)
ExpN2 - Moeda (default 1)
Ex.:
SumMovimCC( 3001”,“3100“,“31001”,“31010”,12,1)
GRAVAORCADO
Permite que um determinado valor calculado pela planilha seja gravado no Arquivo
de Orçamentos.
Sintaxe:
GravaOrcado(ExpC1,ExpN1,ExpN2,ExpN3)
onde:
ExpC1 - Conta Contábil a ser orçada
ExpN1 - Número da célula onde o valor estará contido
ExpN2 - Mês a ser orçado (se nulo, será mês corrente)
397
SALDOCUSTO
Calcula o saldo dos centro de custos extracontábeis.
Sintaxe :
SaldoCusto(ExpC1,ExpC2,ExpC3,ExpC4,ExpN1,ExpN2)
onde:
ExpC1 - Centro de Custo Inicial
ExpC2 - Centro de Custo Final
ExpC3 - Conta Inicial
ExpC4 - Conta Final
ExpN1 - Mês (se nula, assume o mês de referência da database)
ExpN2 - Moeda (se nula, será assumido 1 )
Ex.: SaldoCusto(“1007”, “1099”, “3”, “4”, “10, 1)
SOMACONTAS
Retorna o saldo acumulado de um grupo de contas, de acordo com a sintaxe apresentada. Esta função
considera somente contas de classe “A” – analítica
Sintaxe: SomaContas(ExpC1,ExpN1,ExpN2)
onde:
ExpC1 - Lista de contas, cercada por aspas (“”).
O Separador “:” (dois pontos) forma intervalo de contas De - Até. O separador “,” (vírgula) , informa
separação de contas.
ExpN1 - Mês (default mês da database)
ExpN2 - Moeda (default 1)
Exemplos:
SomaContas(“11101001”,3,1)
Devolve o saldo da conta em questão no mês 3 na moeda 1.
SomaContas(“11101001,11101002,11102237”)
Devolve a soma dos saldos das contas em questão.
SomaContas(“11101001:11102,31101001”)
Devolve a soma dos saldos das contas 11101001 até 11102 mais o saldo da conta 31101001.
Funções Financeiras
SLDBCO
Retorna o saldo bancário em uma data.
Sintaxe: SldBco(ExpC1,ExpC2,ExpC3,ExpD1,ExpN1)
onde:
ExpC1 - Código do Banco
ExpC2 - Agência Bancária
ExpC3 - Conta Bancária
ExpD1 - Data do Saldo
ExpN1 - Moeda do Saldo Bancário
Ex.: SldBco(“409”,”00198”,”011122”, dDataBase,1)
SLDRECEBER
Retorna o saldo a receber em uma data.
Sintaxe: SldReceber(ExpD1,ExpN1,ExpL1)
onde:
ExpD1 - Data do Movimento a Receber.
ExpN1 - Moeda - Default 1
ExpL1 - Se .T. Até a Data, .F. Somente Data (o padrão é .T.)
398
Ex.: SldReceber(Data,1,.T.)
SLDPAGAR
Retorna o saldo a pagar em uma determinada data.
Sintaxe: SldPagar(ExpD1,ExpN1,ExpL1)
onde:
ExpD1 - Data do Movimento a Pagar
( padrão é dDataBase)
ExpN1 - Moeda (padrão é 1)
ExpL1 - Se .T. Até a Data, .F. Somente Data (padrão é .T.)
Ex.: SldPagar(dDataBase,1,.T.)
SLDCLIENTE
Retorna o saldo a receber do cliente em uma determinada data.
Sintaxe: SldCliente(ExpC1,ExpD1,ExpN1,ExpL1)
onde:
ExpC1 - Cliente+Loja
ExpD1 - Data do Movimento a Receber
(padrão é dDataBase)
ExpN1 - Moeda
ExpL1 - Se .T. considera o saldo do SE5
(padrão é .T.)
Ex.: SldCliente(“00000101”,dDataBase)
SLDFORNECE
Retorna o saldo a pagar do fornecedor em uma data
Sintaxe: SldFornece(ExpC1,ExpD1,ExpN1,ExpL1)
onde:
ExpC1 - Fornecedor+Loja
ExpD1 - Data do Movimento a Pagar (padrão é dDataBase)
ExpN1 - Moeda - (padrão é 1)
ExpL1 - Se .T. considera o saldo do SE5
(padrão é .T.)
Ex.: SldFornece(“00000101")
FINNATPRV
Retorna o valor previsto de cada natureza.
Sintaxe: FinatPrv(ExpC1,ExpD1,ExpD2,ExpN1)
onde:
ExpC1 - Natureza a ser Pesquisada
ExpD1 - Data Inicial para cálculo
ExpD2 - Data Final de cálculo
ExpN1 - Moeda de Saída
Ex.:
FinNatPrv(“R001”,CtoD(“01/01/98”),dDataBase,1)
FINNATREA
Retorna o valor realizado da Natureza.
SintaxeFinNatRea(ExpC1,ExpD1,ExpD2,ExpN1)
onde:
ExpC1 - Natureza a ser Pesquisada
ExpD1 - Data Inicial para cálculo
ExpD2 - Data Final de cálculo
ExpN1 - Moeda de Saída
Ex.: FinNatRea(“R001”,CtoD(“01/01/98”),dDataBase,1)
FINNATORC
399
ROTE I RO P ARA I NSTA L AÇÃO DO TOPCON NECT COM SQL / SERVER 7 . 0 M I CROSOFT :
• O Windows NT 4.0 deve ser da versão em inglês e Ter o service Pack atualizado(caso possua estações
Workstation as recomendações de service pack atualizado deve ser aplicado na estação).
• Na instalação do SQL de ser selecionada a opção Custom Character Set/sort order/Unicode
Collation/Character Set: 1252/ISO CHARACTER SET (DEFAULT)
• SORT ORDER: BINARY ORDER E UNICODE COLLATION/LOCALE IDENTIFIER:BINARY ORDER
• No "Query Analyzer"(Ferramenta do SQL/Server 7.0) executar SP_HELPSORT, para verificar se o SQL,
está Configurado como Binary Order (“Sort Order = 50, bin_iso_” ), caso não esteja DEVERÁ SER REFEITA
A INSTALAÇÃO DO SQL SERVER.
• Acessar a Ferramenta Enterprise Manager do Microsoft SQL/Server 7.0, no servidor SQL destinado para o
Siga, abrir a árvore indicada pelo sinal de "+" ao lado esquerdo deste Server.
• Abrir a pasta Databases, clique com o botão direito sobre qualquer Database e escolha New Database.
Onde o Nome deste Database, por exemplo, será DADOSADV, cria-lo com o tamanho previamente
definido e demais parametros default , e em TRANSACTIO LOG será definido a área destinada a Log e o
ideal que seja em outro disco (NÃO OUTRA PARTIÇÃO) diferente do que estiver armazenado o DATABASE,
400
o tamanho também deverá ser previamente definido. Ex.: DATABASE 500MB e em TRANSACTION LOG
150MB.
• E m PROPERT I ES / OPT I O NS d o D AT A B ASE a opção "Truncat Log on Checkpoint", tem a função de
estratégia de Backup, se a empresa optar por efetuar Backup`s de Log, tal opção poderá ficar
desmarcada.
• A g o r a e n t r e e m Sec u r i t y e e m L o g i n s, e com o botão direito sobre qualquer outro login, escolha New
Login, seguindo o exemplo, Nome = SIGA, ativar o SQL Server authentication Password = SIGA, Server
Roles marcar a opção SYSTEM ADMINSTRATORS e em DATABASE ACCESS atribuir permissões (permit)
para o database criado, no caso DADOSADV.
• A parte do SQL Server está p ronta. Agora resta apenas a configu ração do TOPConnect Manager e do
SigaAd v.
• I n s t a l a r o T OPCo n n ec t , e a p ó s o t e r m i n o d o I n s t a l l , e n c e r r a r t o d o s o s s e r v i ç o e r e i n i c i a r o
Se r v i d o r , Caso o processo seja de At ualização do TOPConnect _1 para TOPConnect _2, deve ser efet uada a
re moção do TOPConnect_1(e o q ue for referen te ao topconnect ) at ravés de Adicionar e Re mover
Prog ra mas que está no Painel de Cont role do Windows NT, antes de Instalar o TOPConnect_2.
• T o p c o n n ec t _ 2 / Em Propriedades de Ambiente. Configuração do OD BC SQL S e r v e r Se t u p : Nam e =
TOPSQL, SERVER=(nome do servidor ) [ Ca s o o TOPc o n n e c t e s t e j a n o m es m o se r v i d o r q u e o
SQL / S e r v e r d e v e - se m a n t e r a o p ç ã o LOCAL – Desta forma a conexão entre o TOPConnect e o SQL
não estará trafegando na Rede ] , NEXT > .
• Marcar a opções () With SQL Server authentication using a login ID .... e [] Connect to SQL Server to
obtain default setings .... Login ID : S I GA , Password .:S I GA . NEXT >
• Marcar.: [] Change the default database to: ( Selecionar o Database criado para o Siga) e desmarcar as
opções [] Use ANSI quoted e [] Use ANSI nulls, paddings and warnings . NEXT > .
• Próxima tela marcar [] Perform Translation for character data, e os demais parametros serão marcados
deacordo com a política de administração do Banco.
• Selecionar na Barra de Ferramentas do Topconnect o ícone = a uma Chave ( ou Editar Licenças), para que
possa ser detectado o nº de série, da máquina e assim entrar em contato com o suporte Topconnect
(CL I ENTE DEVERÁ E NTR AR EM CO NTA TO COM O ATEN D I ME NTO D O D I S K -S I G A. : ( 0 x x 1 1 ) 3 9 8 1 -
7 1 0 0 )para obter a chave de acesso conforme a quantidade de usuários adquiridos.
• S I GA A D V A NCED 4 . 0 7 : No diretório Sigaadv\WINSQL, existe um arquivo chamado ADV97.INI. Edite-o,
os parâmetros corretos para o SigaAdv com SQL Server são: D a t a b a se = MSSQL 7 , A l i as = T OPSQL,
Co n t y p e = NPIPE, S e r v e r = NOME do servidor NT com o TOPConnect.
• AP 5 : Localizar em AP5\BIN o arquivo AP5SRV.ini e edita-lo, neste arquivo deverá ser configurado a
clausula [TOPCONNECT] como segue o exemplo conformo o padrão adotado neste roteiro:
[TopConnect]
DataBase=MSSQL7
Server= *nome do servidor ou o endereço IP do servidor
ALIAS=TOPSQL
Contype=NPIPE ou Contype=TCPIP *dependendo da opção do Server.
• Ca s o se j a n e c e ss á r io a m i g r aç ã o d e b a se D BF p a r a o Ba n c o v erifique, antes de executar o
DBF2SQL, o DBF2SQL.INI. O Alias tem que ser igual à MSSQL7/TOPSQL, neste exemplo.
• Está pronta toda sua configuração.
• CASO seja necessário que o" SQL SERVER deva estar em UM SERVIDOR NT E TOPCONNECT EM OUTRO
NT".
401
• No 1º Instalar o SQL SERVER. No 2º instalar o client do SQL e o topconnect, e apontar o client para a 1ª
máquina, o TOPCONNECT deve apontar para o SQL Server (1ª máquina) o ADV97.INI deverá indicar o
no me do serv idor da 2ª máquina, aonde o Topconnect está instalado.
1.1. A m b ie n t e D e se j á v e l p a r a u m a i n s t a l aç ã o d e 2 5 u s u á r i o s :
Se r v i d o r W i n d o w s NT 4 . 0 c o m T o pCo n n e c t , Ba n c o d e d a d o s
MsSq l / O r a c l e / I n f o r m i x / ..., Si g aA d v a n c e d / A P5 .
402
403
• CL I ENTE S I GA A D VA NCED
• No diretório AP5\BIN, existe um arquivo chamado AP5SRV.INI. Edite-o, os parâmetros corretos para O
PROTHEUS com SQL Server são: Database = MSSQL 7, Alias = TOPSQL, Contype = NPIPE, Server =
NOME do servidor NT com o TOPConnect.
MsExecAu t o
Objetivo
Aplicação
Vantagens
Procedimentos
404
1. Sem Interface
2. Com Interface
Exemplo:
Local aRotAuto := {}
Local nOpc := 3 // inclusao
Private lMsHelpAuto := .t. // se .t. direciona as mensagens de help para o arq. de log
Private lMsErroAuto := .f. //necessario a criacao, pois sera //atualizado quando
houver
//alguma incosistencia nos parametros
Begin Transaction
aRotAuto:= {{'B1_COD' ,'1010' ,Nil},;
{'B1_DESC' ,'Produto teste',Nil},;
{'B1_TIPO' ,'PA' ,Nil},;
{'B1_UM' ,'UN' ,Nil},;
{'B1_LOCPAD' ,'01' ,Nil},;
{'B1_PICM' ,0 ,Nil},;
{'B1_IPI' ,0 ,Nil},;
{'B1_PRV1' ,100 ,Nil},;
{'B1_LOCALIZ' ,'N' ,Nil},;
{'B1_CODBAR' ,'789888800001' ,Nil}}
MSExecAuto({|x,y| mata010(x,y)},aProduto,nOpc)
If lMsErroAuto
DisarmTransaction()
break
EndIf
End Transaction
If lMsErroAuto
/*
Se estiver em uma aplicao normal e ocorrer alguma incosistencia nos parametros
passados,mostrar na tela o log informando qual coluna teve a incosistencia.
*/
Mostraerro()
Return .f.
EndIf
Return .t.
Ja para rotinas que possuem interface, devemos usar a MSExecAuto, pois a mesma
tem a função de guardar o ambiente , executar a função automatica e retornar de
onde parou.
Exemplo:
User Function IncProd()
405
Local aRotAuto := {}
Local nOpc := 3 // inclusao
Private lMsHelpAuto := .t. // se .t. direciona as mensagens de help para o arq. de log
Private lMsErroAuto := .f. //necessario a criacao, pois sera //atualizado quando
houver
//alguma incosistencia nos parametros
Begin Transaction
aRotAuto:= {{'B1_COD' ,'1010' ,Nil},;
{'B1_DESC' ,'Produto teste',Nil},;
{'B1_TIPO' ,'PA' ,Nil},;
{'B1_UM' ,'UN' ,Nil},;
{'B1_LOCPAD' ,'01' ,Nil},;
{'B1_PICM' ,0 ,Nil},;
{'B1_IPI' ,0 ,Nil},;
{'B1_PRV1' ,100 ,Nil},;
{'B1_LOCALIZ' ,'N' ,Nil},;
{'B1_CODBAR' ,'789888800001' ,Nil}}
MSExecAuto({|x,y| mata010(x,y)},aProduto,nOpc)
If lMsErroAuto
DisarmTransaction()
break
EndIf
End Transaction
If lMsErroAuto
/*
Se estiver em uma aplicao normal e ocorrer alguma incosistencia nos parametros
passados,mostrar na tela o log informando qual coluna teve a incosistencia.
*/
Mostraerro()
Return .f.
EndIf
Return .t.
Value: 0
--------------------------------------------------------------------------------
Value: -1
Meaning: Você está tentado executar a função TC_Connect sem ter uma camada de comunicação.
--------------------------------------------------------------------------------
406
Value: -2
Meaning: Você está tentado executar uma função sem estabelecer conexão previa.
--------------------------------------------------------------------------------
Value:-4
Recovery:
--------------------------------------------------------------------------------
Constant Name: TCF_No_More_Connections
Value: -6
--------------------------------------------------------------------------------
Value: -7
Meaning: Há uma diferença entre o formato do registro corrente que o AS/400 arquiva e o formato digitado
na PC Table.
Recovery: Obtenha o registro do formato AS/400 para o arquivo usando no programa do TClient, e check a
tabela
--------------------------------------------------------------------------------
Value: -10
Meaning: Você está tentando abrir um arquivo que não podê ser encontrado
--------------------------------------------------------------------------------
Value: -11
Meaning: Você está tentando abrir um arquivo que não está associado com um processo no AS/400.
--------------------------------------------------------------------------------
Value: -12
407
--------------------------------------------------------------------------------
Value: -13
--------------------------------------------------------------------------------
Value: -14
Meaning: Você tem especificado um número de campo chave maior que o arquivo, como uma função de
acesso chave.
Value: -16
Meaning: Você está tentando abrir um arquivo, mas o número de máximo de arquivos ao servidor excedeu.
Recovery: Feche um dos arquivos abertos e tente abrir o arquivo outra vez.
--------------------------------------------------------------------------------
Value: -17
--------------------------------------------------------------------------------
Value: -18
--------------------------------------------------------------------------------
Value: -19
408
--------------------------------------------------------------------------------
Value: -20
--------------------------------------------------------------------------------
Value: -21
--------------------------------------------------------------------------------
Value: -23
--------------------------------------------------------------------------------
Value: -24
Meaning: Você está tentando uma operação com um arquivo que não está aberto.
--------------------------------------------------------------------------------
Value: -25
Meaning: O registro solicitado não pode ser encontrado como uma função de acesso ao campo chave.
--------------------------------------------------------------------------------
Value: -26
Meaning: Você chegou no fim do arquivo ou o fim de registros que estão em Read_Multiple.
--------------------------------------------------------------------------------
Value: -27
409
Recovery: Verifique o valor da chave de índice em registro. Você pode estar tentado escrever um registro
com uma chave duplicada ou database está cheio.
--------------------------------------------------------------------------------
Value: -28
--------------------------------------------------------------------------------
Value: -29
Recovery: Verifique a chave utilizada na criação, e assegure que o registro não esteja Locado.
--------------------------------------------------------------------------------
Value: -30
Recovery: Verifique a chave utilizada, e assegure que o registro não está Locado.
--------------------------------------------------------------------------------
Value: -31
--------------------------------------------------------------------------------
Value: -33
Recovery: Isto indica que a conexão com o AS/400 não pode ser completada porque a chave do TOPConnect
é inválida ou está expirada.
--------------------------------------------------------------------------------
Value: -34
410
--------------------------------------------------------------------------------
Value: -35
Recovery:
--------------------------------------------------------------------------------
Value: -58
Recovery: Indica que não pode ter o desempenhado necessario devido insuficiência de memória corrente
para a situação.
--------------------------------------------------------------------------------
Value: -90
Recovery: Indica que o trabalho não pode ser feito devido a insuficiência de Memória do PC . Corrija a
situação.
Hardlock
1-) Qual o objetivo do”Hardlock” ?
Juntamente com a versão 7.10 a Microsiga disponibiliza um hardware de proteção que tem por objetivo a
segurança das informações usando algoritmos de criptografia (recurso para proteção de mensagens
eletrônicas) baseados em chaves de 128 bits, liberando mecanismos mais eficientes para proteger o sistema
contra acessos indevidos. Aliado a isso, mais agilidade no processo de liberação de senhas e ganho de
performance nos processos de controle aos acessos simultâneos (semaforização) são obtidos.
--------------------------------------------------------------------------------
2-) O cliente recebeu a versão 7.10 mas ainda não recebeu o “Hardlock” o que deve-se fazer ?
--------------------------------------------------------------------------------
3-) Com quem devo falar na Microsiga para solicitar a contra senha do “Hardlock” ?
O próprio Departamento de Senhas é o responsável pela liberação e envio das contra-senhas do “Hardlock”.
411
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Os testes a partir da versão 7.10 ficam sendo possíveis, sem consumo de licenças do ambiente oficial,
somente na empresa "99 – Teste / Matriz ", ou utilizando-se da senha de emergência.
--------------------------------------------------------------------------------
A empresa "99 - Teste" não requer a utilização nem a autenticação através do “Hardlock”, portanto, seu uso
está liberado. O número de registros que antes era limitado a 50 passa a não existir mais, sendo este
substituído pelo controle de uso por no máximo 2 usuários simultâneos.
--------------------------------------------------------------------------------
7-) Como ficam as liberações no caso em que o “Hardlock”, depois de colocado em uso, falhar?
Para este caso existe o procedimento de liberação da senha de emergência, que neste caso, irá liberar o uso
do sistema até que a substituição ou manutenção seja realizada. Em caso de falha constatada no dispositivo,
este será substituído gratuitamente no 1º ano e ao custo de tabela da Store (Hoje em US$ 43,55) a partir de
então.
--------------------------------------------------------------------------------
Somente um, pois o cliente irá eleger qual "servidor" Protheus também será o servidor de licenças,e este por
sua vez poderá autenticar todos os demais servidores da empresa.
--------------------------------------------------------------------------------
Caso o cliente tenha perdido ou tenha furtado o “Hardlock” ele deverá providenciar um Boletim de ocorrência
e comprar a nova chave de segurança pelo valor de US$ 43,55
--------------------------------------------------------------------------------
10-) O cliente modificou seu ambiente de hardware, ou seja, a máquina quebrou instalou novamente,
mudou para uma máquina nova, etc. O mesmo “Hardlock” funcionará?
Irá funcionar normalmente desde que seja instalado novamente, e reconfigurado o AP7SRV.INI, caso o nome
/ IP da máquina tenha sido alterado.
--------------------------------------------------------------------------------
Na porta paralela ou USB, de acordo com a disponibilidade do Servidor do cliente. O próprio instalador do
AP7 irá solicitar informações quanto a porta e o nome do servidor em que será instalado o “Hardlock”.
--------------------------------------------------------------------------------
12-) Possuo um ambiente com três "sites" distintos, onde dois deles estão centralizados e o terceiro esta
trabalhando de forma independente ? Como este ambiente deverá ser com a utilização do “Hardlock” ?
412
Contratualmente a Microsiga exige um contrato para cada localidade ( física ), portanto, existindo este caso,
o cliente receberá 2 “Hardlock”'s, 1 para ser usado nos que são centralizados, e um adicional para que seja
usado na localidade independente. Cabe salientar que a Microsiga fornece gratuitamente 1 “Hardlock” para
cada contrato de manutenção vigente e caso exista apenas um contrato de manutenção, o cliente deverá
adquirir mais um “Hardlock” pelo preço de US$ 43,55
--------------------------------------------------------------------------------
O mesmo deve entrar em contato com a unidade de Atendimento e relacionamento da Microsiga para que
seja providenciada a sua substituição.
--------------------------------------------------------------------------------
Tecnicamente sim, pois as portas USB's são em média 5x mais rápidas que as paralelas, porém isto não
implicara em maior ou menor performance do sistema, pois a comunicação com a chave de segurança se dá
em raras ocasiões.
--------------------------------------------------------------------------------
Quando por algum motivo qualquer o”Hardlock” , ou a porta em que ele está instalado venha a falhar,
portanto, até sua manutenção, o cliente deverá utilizar a senha emergencial.
--------------------------------------------------------------------------------
16-) O “Hardlock” não funciona mesmo com a contra senha correta, o que devo fazer?
Verifique a configuração da porta ( paralela ou USB ). Realize testes utilizando um outro servidor para ter
certeza se o problema é ou não no Harklock. Cabe salientar que todos os “HardLocks” são testados na
Microsiga no momento da liberação.
--------------------------------------------------------------------------------
17-) Caso o cliente seja um “DataCenter “ e tenha um número de licenças que deva ser distribuído para cada
um de seus clientes, o que fazer ?
17.2 -> Ter um único “HardLock” e controlar os acessos através do ponto de entrada “CHKEXEC” além da
utilização da chave “SEMAFOROKEY” no ambiente (“Environment” corrente) que está configurado no
AP7SRV.INI
--------------------------------------------------------------------------------
O próprio instalador do AP7 solicita as informações necessárias durante este processo para se utilizar o
“Hardlock”. No arquivo .INI do Servidor do AP7, haverão duas sessões conforme abaixo:
[LICENSESERVER]
enable=1
port=porta-do-license-server
[LICENSECLIENT]
server=nome-do-servidor
413
port=porta-do-license-server
--------------------------------------------------------------------------------
Não. O cliente tendo 2 ou mais servidores de aplicação, o mesmo irá eleger um deles para ser o servidor de
licenças, onde então será instalado o “Hardlock”, e a partir deste momento, os demais passarão a pedir
autenticação para ele.
--------------------------------------------------------------------------------
Como o sistema permite que a emissão de relatórios possa ser programada (schedule) é fundamental que se
utilize as rotinas padrões para a emissão dos mesmo. O controle do schedule é feito pela função SetPrint.
Sendo assim, não é suportado interface com data entry durante o processo de relatório, visto que isto
inviabilizará a utilização do mesmo. A não ser em relatórios específicos e que sejam inviáveis a utilização de
shedule (ex. Impressão de Cheques) este procedimento deverá ser adotado corretamente.
Caso exista alguma entrada de dados que seja possível ser assumida qualquer valor apenas no schedule
deve-se adotar o seguinte procedimento :
Usar a variável __cInternet, que se estiver com valor .T. (Verdadeiro) estamos no processo de schedule.
1. Arquivos anexados:
a. .sps - Arquivo encriptado com as Storeds Procedures.
b. .txt - Arquivo que documenta o conteúdo dos arquivos .sps.
c. .pat - Patch do Protheus. ( é necessário solicitar )
2. Instalando o .pat ( se h o u v e r ).
414
de sua versão as datas e alterações das rotinas realizadas junto com o arquivo texto anexo, se as mesmas
não existirem, reapliquem os Patches emergenciais ou façam nova solicitação dos mesmos.
Somente atenderemos as solicitações originadas de e-mails com domínio @microsiga.com.br, e
faremos o envio para esta mesma conta, o solicitante deverá ser sempre o canal de redirecionamento ao
cliente.
Caso não exista o menu, crie. A função que chama o configurador é a CFGX 0 5 1 ( ) .
415
416
417