Olá pessoal…
Hoje vou mostrar uma função que criei que cria automaticamente os complementos de produto através dos produtos já cadastros.
Se você utiliza ou habilitou o complemento de produtos (tabela SB5), se já possui produtos cadastrados, já percebeu que é oneroso ter que cadastrar todos novamente, certo?
Pensando nisso, preparei um código fonte, que percorre todos os produtos criados e os que não tiverem complemento, é criado automaticamente.
Segue abaixo o código:
//Bibliotecas #Include "Protheus.ch" /*/{Protheus.doc} zSB1Compl Função que gera o complemento do produto (SB5) através do produto (SB1) @author Atilio @since 29/08/2017 @version 1.0 @type function @obs Executar como Administrador /*/ User Function zSB1Compl() Processa({|| fProcessa()}, "Processando...") Return /*----------------------------------------------------------* | Func.: fProcessa | | Desc.: Função de processamento para gravar o complemento | *----------------------------------------------------------*/ Static Function fProcessa() Local aArea := GetArea() Local nAtual := 0 Local nTotal := 0 Local nOk := 0 Local cOk := "" Local cMsg := "" Local lPosUM := ( SB5->(FieldPos('B5_UMIND')) != 0) //Abre o cadastro de produtos DbSelectArea('SB1') SB1->(DbSetOrder(1)) //B1_FILIAL + B1_COD SB1->(DbGoTop()) Count To nTotal //Abre o cadastro de complemento DbSelectArea('SB5') SB5->(DbSetOrder(1)) //B5_FILIAL + B5_COD SB5->(DbGoTop()) //Posiciona no topo e percorre os registros SB1->(DbGoTop()) While ! SB1->(Eof()) nAtual++ IncProc("Processando "+cValToChar(nAtual)+" de "+cValToChar(nTotal)+" ("+AllTrim(SB1->B1_COD)+")...") //Se não existir complemento If ! SB5->(DbSeek(FWxFilial('SB5') + SB1->B1_COD)) //Foi feito através de RecLock, pois o MsExecAuto da MATA180 estava travando RecLock('SB5', .T.) B5_FILIAL := FWxFilial('SB5') B5_COD := SB1->B1_COD B5_CEME := SB1->B1_DESC If lPosUM B5_UMIND := '1' EndIf SB5->(MsUnlock()) lMsErroAuto := .F. nOk++ cOk += "- "+Alltrim(SB1->B1_COD)+";" + CRLF EndIf SB1->(DbSkip()) EndDo //Se tiver erros ou inclusões, mostra mensagem If nOk != 0 cMsg := "Foram analisados "+cValToChar(nTotal)+" produtos..." + CRLF + CRLF cMsg += "Sucesso na inclusão do complemento de "+cValToChar(nOk)+" produto(s):"+CRLF cMsg += cOk + CRLF Aviso("Atenção", cMsg, {"Ok"}, 2) EndIf //Atualiza o grupo de perguntas If MsgYesNo("Deseja atualizar o parâmetro do cadastro de produtos (F12)?", "Atenção") u_zAtuPerg("MTA010", "MV_PAR02", 1) EndIf MsgInfo("Processo concluído.", "Atenção") RestArea(aArea) Return
Avisos:
Pessoal, o exemplo acima foi montado para um cenário onde tanto a SB1 como a SB5 estiverem como Compartilhadas (X2_MODO igual a C). Assim, ele vai sempre gerar 1 registro para cada SB5 que não tenha SB1.
Se o seu cenário for diferente, por exemplo, a SB5 for Exclusiva e a SB1 for Exclusiva, ai no if da linha 49, basta mudar para ! SB5->(DbSeek(SB1->B1_FILIAL + SB1->B1_COD)) . Que dessa forma, ele vai tentar buscar o registro para aquela filial e código atual da SB1. E na linha 52, ao invés de FWxFilial(“SB5”), você deve alterar para SB1->B1_FILIAL.
Agora se o seu cenário, for onde um tipo de compartilhamento for diferente do outro, por exemplo, SB5 for Exclusiva e a SB1 for Compartilhada, você terá que adaptar para que as filiais sejam percorridas, por exemplo, em um laço de repetição com For ou While, e ai dentro desse laço, acionar o DbSeek e RecLock na SB5.
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Olá Dan,
Obrigado por compartilhar o material, só que tem um problema aí. Permita-me corrigi-lo.
A linha 49 está levando em consideração apenas o código SB5 = SB1, porém sem considerar a filial.
Caso contrário, ele vai adicionar SB5 de todas as filiais contidas na sua SB1 e não apenas da filial da SB1 que não tem SB5.
Obrigado e até mais.
Fala Felipe, tudo joia?
Primeiramente, obrigado pelo comentário e feedback.
O cenário em que montei o artigo foi onde o X2_MODO esta igual para a SB5 e SB1 (acho que esqueci de mencionar no corpo do artigo), ambos como “C” de Compartilhados.
Por isso, não vai acontecer de “adicionar SB5 de todas as filiais”, ele só vai adicionar 1 único registro pois esta usando FWxFilial.
Quanto a pedir permissão, acha jovem, não precisa pedir não, pode ficar em paz. Se possível então, mande o trecho de código com a correção para o cenário que você pegou, que daí eu compartilho aqui no artigo para ajudar outras pessoas, onde o X2_MODO for diferente de Compartilhado entre SB1 e SB5 (ambas forem exclusivas ou uma ou outra for exclusiva).
Enquanto aguardo o fonte que você vai enviar para eu complementar no artigo, vou deixar um aviso no fim dele, em que ele foi preparado numa base com ambas as tabelas compartilhadas, já citando as possíveis soluções com os outros tipos de compartilhamento.
Fico no aguardo.
Grande abraço.
Não consegui responder direto na sua mensagem por um problema no meu navegador aqui, mas a partir da linha 42 troquei para:
//Posiciona no topo e percorre os registros
SB1->(DbGoTop())
While ! SB1->(Eof()) .AND. Alltrim(SB1->B1_FILIAL+SB1->B1_COD) == Alltrim(SB5->B5_FILIAL+SB5->B5_COD)
Não está ideal, mas está funcionando hahahhaha.
Abraços
Opa, obrigado pelo feedback Felipe.
Eu tinha achado que era na linha do Seek e dentro do RecLock que você estava falando (no comentário do dia 30/03). Em todo o caso eu já havia atualizado o artigo (com um aviso no fim) para quem tem ambas tabelas exclusivas (que é o seu cenário). Depois se quiser dar uma olhada mais acima, se quiser complementar com algo, fico no aguardo.
Quanto ao trecho, ele deve ficar similar ao abaixo (para criar a SB5 conforme a SB1 posicionada), coloquei apenas o trecho das linhas 42 a 58:
Grande abraço.