Algumas pessoas estavam me perguntando como atualizar o campo memo no Protheus já que este trabalha com a tabela SYP (Descrição dos campos memos)? Tabelas como a do cadastro de produto é uma das tabelas que usam campos mesmo, no caso tem os campos “Descrição LI”, “Descrição em inglês” e “Descrição em português”. O processo de atualização é bem simples, vamos exemplificar usando o cadastro padrão de produtos (SB1). Irei definir um layout do arquivo texto, irei pedir ao meu usuário que crie um arquivo texto contendo as seguintes colunas: Código do produto; código da tabela SYP, descrição. O código do produto deverá ser o mesmo existente na tabela de produtos O código da tabela SYP, deverá ser o mesmo conteúdo existente no campo correspondente ao campo memo, irei trabalhar com os campos B1_DESC_GI e B1_VM_GI (Descrição da LI), este campo tem o seguinte inicializador padrão: E_MSMM(SB1->B1_DESC_GI,48) A cada 48 caracteres do meu texto, ou a cada quebra de linha será uma linha na minha tabela SYP. E teremos também no meu layout a descrição que quero incluir, pode ser uma coluna só onde você fará a quebra dos 48 caracteres ou peça ao usuário para criar várias colunas que corresponda à quantidade de linha na tabela SYP.
Produto;Número LI;Desc1;Desc2;Desc3;Desc4 3915008;069418;PARADA DE EMERGENCIA FANT.; texto segunda linha; texto terceira linha; texto quarta linha com xxxxxxxxxxxxxxxxxxxxxxxx 3729745;069725;BARRA INFERIOR DEPEN F201 MAQ; texto segunda linha; texto terceira linha; texto quarta linha com xxxxxxxxxxxxxxxxxxxxxxxx 3729740;069726;BARRA INFERIOR DEPENADEIRA F20; texto segunda linha; texto terceira linha; texto quarta linha com xxxxxxxxxxxxxxxxxxxxxxxxA codificação abaixo é apenas uma sugestão, se tiverem outras sugestões fiquem a vontade para compartilhar. Vamos ao que interessa:
#INCLUDE "PROTHEUS.CH" #INCLUDE "TOPCONN.CH" User Function MCOM009() Local cTitulo := "Ajustar descrição da LI do cadastro de Produtos" Local nOpcao := 0 Local aButtons := {} Local aSays := {} Private cArea := GetArea() Private cPerg := Padr("MCOM009",10) Private oProcess ajustaSx1(cPerg) pergunte(cPerg, .F.) AADD(aSays,OemToAnsi("Ajustar descrição da LI do cadastro de Produtos vindos de um arquivo CSV.")) AADD(aSays,"") AADD(aSays,OemToAnsi("Clique no botão PARAM para informar o arquivo que será importado.")) AADD(aSays,"") AADD(aSays,OemToAnsi("Após isso, clique no botão OK.")) AADD(aButtons, { 1,.T.,{|o| nOpcao:= 1,o:oWnd:End()} } ) AADD(aButtons, { 2,.T.,{|o| nOpcao:= 2,o:oWnd:End()} } ) AADD(aButtons, { 5,.T.,{|| pergunte(cPerg,.T.) } } ) FormBatch( cTitulo, aSays, aButtons,,200,530 ) if nOpcao = 1 oProcess := MsNewProcess():New( { || MCOM009I(MV_PAR01) } , cTitulo , "Aguarde..." , .F. ) oProcess:Activate() endif RestArea(cArea) Return
Static Function MCOM009I(cArquivo) Local cLinha := "" Local cTexto := "" Local nI := 0 Local nHdl Local nTamArq Local nTamLinha Local nLinhas Local aDados := {} Local nCont Local cLinhas Local cAviso := "" Local aStrutSC1 := {} Local nItem := 0 Local nTotal := 0 Local lPrim := .T. Local nPrim := 1 Local alin := {} Local cErro := "" Local cProduto := "" Local cChave := "" Local cDesc1 := "" Local cDesc2 := "" Local cDesc3 := "" Local cDesc4 := "" Local aDescYP := {} Local cTipo := "" Local nColunas := 0 Local nDesc1, nDesc2, nDesc3, nDesc4 := 0 if (Upper(Right(Alltrim(cArquivo),4)) != ".CSV" ) MsgStop("Apenas arquivos com extensão CSV são aceitos!"+CRLF+"Verifique o arquivo informado!","Atenção") Return EndIf if !File(cArquivo) MsgStop("O arquivo "+Alltrim(cArquivo)+" não existe, favor informar um arquivo existente!","Atenção") Return EndIf nHdl := fOpen(cArquivo) If nHdl == -1 IF FERROR()== 516 ALERT("Feche a planilha que gerou o arquivo.") EndIF EndIf //+---------------------------------------------------------------------+ //| Verifica se foi possível abrir o arquivo | //+---------------------------------------------------------------------+ If nHdl == -1 MsgAlert("O arquivo de nome "+Alltrim(cArquivo)+" nao pode ser aberto! Verifique os parametros.","Atencao!") Return Endif //+---------------------------------------------------------------------+ //| Posiciona no Inicio do Arquivo | //+---------------------------------------------------------------------+ FSEEK(nHdl,0,0) //+---------------------------------------------------------------------+ //| Traz o Tamanho do Arquivo TXT | //+---------------------------------------------------------------------+ nTamArq:=FSEEK(nHdl,0,2) //+---------------------------------------------------------------------+ //| Posicona novamemte no Inicio | //+---------------------------------------------------------------------+ FSEEK(nHdl,0,0) //+---------------------------------------------------------------------+ //| Fecha o Arquivo | //+---------------------------------------------------------------------+ fClose(nHdl) FT_FUse(cArquivo) //abre o arquivo FT_FGOTOP() //posiciona na primeira linha do arquivo nTamLinha := Len(FT_FREADLN()) //Ve o tamanho da linha FT_FGOTOP() //+---------------------------------------------------------------------+ //| Verifica quantas linhas tem o arquivo | //+---------------------------------------------------------------------+ nLinhas := nTamArq/nTamLinha oProcess:SetRegua1(nLinhas) aDados:={} nCont := 0 While !FT_FEOF()// .and. ncont < 16 oProcess:IncRegua1('Validando Linha: ' + Alltrim(Str(nCont))) clinha := FT_FREADLN() if !empty(cLinha) AADD(aDados,Separa(cLinha,";",.T.)) //Armazena no array aDados todas as linhas do TXT endif FT_FSKIP() nCont++ EndDo FT_FUse() fClose(nHdl) aStrutSC1 := dbStruct() oProcess:SetRegua1(len(aDados)) cErro := "" dbSelectArea("SB1") SB1->(dbSetOrder(1)) For nI := 1 to len(aDados) aColunas := {} cProduto := aDados[nI,1] cChave := iif( !Empty(aDados[nI,2]) , aDados[nI,2] , fUltimo() ) cTipo := iif( !Empty(aDados[nI,2]) , "A" , "N" ) nColunas := 0 For y := 1 to len(aDados[nI]) nColunas += 1 Next cDesc1 := iif(nColunas>=3, aDados[nI,3], "") If Empty(cDesc1) MsgStop("É obrigatório ter pelo menos a primeira descrição!") Return Endif cDesc2 := iif(nColunas>=4, aDados[nI,4], "") cDesc3 := iif(nColunas>=5, aDados[nI,5], "") cDesc4 := iif(nColunas>=6, aDados[nI,6], "") SB1->(dbGoTop()) if SB1->(!dbSeek(xFilial("SB1")+cProduto)) cErro += Alltrim(cProduto)+CRLF oProcess:IncRegua1("Produto "+Alltrim(cProduto)+" não existe...") Else oProcess:IncRegua1("Atualizando produto " + Alltrim(cProduto)) //Verifica se a chave existe, se existir deve excluir todos os registros que contem a chave dbSelectArea("SYP") SYP->(DbSetOrder(1)) SYP->(DbGoTop()) If(SYP->(DbSeek(xFilial("SYP") + cChave, .T.))) oProcess:SetRegua2( SYP->(RecCount()) ) While SYP->(!Eof()) ; .And. ( Alltrim(SYP->YP_CHAVE) == Alltrim(cChave)) ; .And. ( Alltrim(SYP->YP_CAMPO) == "B1_DESC_GI") ; .And. ( SYP->YP_FILIAL == xFilial("SYP")) oProcess:IncRegua2("Excluindo sequencia " + SYP->YP_SEQ + "...") RecLock("SYP",.F.) SYP->(dbDelete()) SYP->(MsUnlock()) SYP->(DbSkip()) End While Endif SYP->(DbCloseArea()) //Inserir os registros na tabela SYP aDescYP := {} if !Empty(cDesc1) aadd(aDescYP,{cChave,cDesc1}) Endif if !Empty(cDesc2) aadd(aDescYP,{cChave,cDesc2}) Endif if !Empty(cDesc3) aadd(aDescYP,{cChave,cDesc3}) Endif if !Empty(cDesc4) aadd(aDescYP,{cChave,cDesc4}) Endif oProcess:SetRegua2( len(aDescYP) * 2) dbSelectArea("SYP") For i := 1 to len(aDescYP) Begin Transaction RecLock("SYP",.T.) SYP->YP_FILIAL := xFilial("SYP") SYP->YP_CHAVE := aDescYP[i,1] SYP->YP_SEQ := StrZero(i,3) SYP->YP_TEXTO := aDescYP[i,2] SYP->YP_CAMPO := "B1_DESC_GI" SYP->(MsUnlock()) DbCommit() oProcess:IncRegua2("Incluindo Descrição LI - Registro " + StrZero(nI,4) + "...") End Transaction Next if cTipo=="N" RecLock("SB1",.F.) SB1->B1_DESC_GI := cChave SB1->(MsUnlock()) Endif Endif Sleep(100) dbSelectArea("SB1") Next nI if !Empty(cErro) Aviso("ATENÇÃO", "Alguns produtos não puderam ser importados por não existirem na tabela padrão de produtos."+CRLF+cErro,{"OK"},3) Endif if(mv_par02==1) fRename(Upper(Alltrim(cArquivo)),Upper(Alltrim(cArquivo))+".processado") Endif oProcess:IncRegua1("Atualização finalizada...") oProcess:IncRegua2("") Return
Static Function fUltimo() local cUltimo := "" Local cQuery := "" cQuery := " SELECT MAX(YP_CHAVE) ULTIMO " cQuery += " FROM " + RetSqlName("SYP") cQuery += " WHERE YP_FILIAL = '"+XFILIAL("SYP")+"' " cQuery += " AND D_E_L_E_T_ = ' ' " If ( SELECT("TMPSYP") ) > 0 dbSelectArea("TMPSYP") TMPSYP->(dbCloseArea()) EndIf TCQUERY cQuery NEW ALIAS "TMPSYP" IF TMPSYP->(!Eof()) cUltimo := StrZero(Val(TMPSYP->ULTIMO)+1,6) Endif TMPSYP->(dbCloseArea()) Return(cUltimo)
static function ajustaSx1(cPerg) PutSx1(cPerg, "01", "Arquivo ?","","", "mv_ch1", "C",99, 0, 0, "G", "","DIR","","","mv_par01","","","","","","","","","","","","","","","","",{"Informe o arquivo para importar,","obrigatóriamente deve ser .CSV","",""},{"","","",""},{"","",""},"") PutSx1(cPerg, "02", "Renomear?","","", "mv_ch2", "N", 1, 0, 2, "C", "", "","","","mv_par02","Sim","Si","Yes","","Nao","No","No") Return