Função que converte o valor do Soma1 em AdvPL

Olá pessoal…

Hoje vou mostrar uma rotina desenvolvida para converter valores gerados pelo Soma1 (como por exemplo, após o 99, vir o 9A, depois o 9B, 9C, 9D até chegar no ZZ).


Foram desenvolvidas duas rotinas, a primeira converte 100% dos casos, porém é bem mais demorada, pois é feito um While, percorrendo até chegar no valor do soma1.

A segunda, pelos testes realizados, converte 100% quando o valor tem 1 posição ou duas (ou seja, no tamanho máximo de “ZZ”), a partir de 3 posições, o fator fica impreciso no valor de AB0, pois não consegui chegar em um fator de conversão exato.

AdvPL

AdvPL

Abaixo o código desenvolvido com as duas funções.

//Bibliotecas
#Include "Protheus.ch"

/*/{Protheus.doc} zCnvSoma1
Função de conversão do Soma1
@type function
@author Atilio
@since 03/08/2016
@version 1.0
	@param cValor, character, Valor do Soma1
	@return nValConv, Valor convertido
	@example
	u_zCnvSoma1("ZZZ")
/*/

User Function zCnvSoma1(cValor)
	Local aArea    := GetArea()
	Local nValConv := 0
	Local cAtual   := ""
	Default cValor := "0"
	
	//Definindo o atual como 0
	cAtual := StrZero(0, Len(cValor))
	cAtual := StrTran(cAtual, '0', '9')
	
	//Enquanto o valor atual for diferente do parâmetro
	While cAtual != cValor
		nValConv++
		cAtual := Soma1(cAtual)
	EndDo
	
	RestArea(aArea)
Return nValConv

/*/{Protheus.doc} zCnvTipo2
Função para conversão do Soma1 (sem utilizar o While)
@type function
@author Atilio
@since 03/08/2016
@version 1.0
	@param cNumero, character, Valor do Soma1
	@return nValor, Valor Convertido
	@example
	u_zCnvSoma1("ZZ")
	@obs Essa função não foi finalizada 100%!
	Não foi encontrado um fator exato de conversão, em testes realizados, com valores de tamanho 1 e 2, a função funciona
	perfeitamente (por exemplo, A0, ZZ, Z, M9, etc), porém para valores de tamanho 3 para cima não.
	Para valores de tamanho 1, a rotina funciona
	Para valores de tamanho 2, a rotina funciona
	Para valores de tamanho 3, a inconsistência começa partir do AB0  (após o AAZ)  - 2357  registros
	Para valores de tamanho 4, a inconsistência começa partir do 9AB0 (após o 9AAZ) - 11356 registros
/*/

User Function zCnvTipo2(cNumero)
	Local aArea     := GetArea()
	Local nValor    := 0
	Local lSoNumero := .T.
	Local nAtual    := 0
	Local cAscii    := ""
	Local nPosIni   := 0
	Local cCaract   := ""
	Local nValAux   := 0
	Local cZeros    := ""
	Local cAscii    := ""
	cNumero := Upper(cNumero)
	
	//Percorre os valores
	For nAtual := 1 To Len(cNumero)
		cCaract := SubStr(cNumero, nAtual, 1)
		
		//Se tiver alguma letra no numero
		If cCaract $ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
			If nPosIni == 0
				nPosIni := nAtual
			EndIf
			lSoNumero := .F.
			Exit
		EndIf
	Next
	
	//Se tiver somente numero, converte com Val
	If lSoNumero
		nValor := Val(cNumero)
		
	Else
		nValor := 0
		
		//Percorre os valores
		For nAtual := 1 To Len(cNumero)
			cCaract := SubStr(cNumero, nAtual, 1)
			cZeros  := Replicate("0", Len(cNumero)-nAtual)
			
			//Se tiver alguma letra no numero
			If cCaract $ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
				cAscii := cValToChar(Asc(cCaract) - 64 + 9)
				
				//Se for a partir da segunda posição e não for a última
				If nAtual > nPosIni .And. nAtual != Len(cNumero)
					nValAux := Val(cAscii + cZeros) + Iif(nAtual != Len(cNumero), 26 * (Asc(cCaract) - 64), 0)
					nValAux *= Val(cAscii)
					nValAux += (26 + Val(cAscii))
					nValor += nValAux
					
				Else
					nValor += Val(cAscii + cZeros) + Iif(nAtual != Len(cNumero), 26 * (Asc(cCaract) - 64), 0)
				EndIf
			
			//Se for somente números
			Else
				//Se for a partir da segunda posição e não for a última
				If nAtual > nPosIni .And. nAtual != Len(cNumero)
					nValor += Val(cCaract + cZeros) + (36 * 26) + (26*Val(cCaract))
				Else
					nValor += Val(cCaract + cZeros)
				EndIf
			EndIf
		Next		
	EndIf
	
	RestArea(aArea)
Return nValor

Esses e outros códigos, estão disponíveis gratuitamente no nosso GitHub, acesse em github.com/dan-atilio/AdvPL.

Bom pessoal, por hoje é só.
Abraços e até a próxima.

About Dan_Atilio

Analista e desenvolvedor de sistemas na TOTVS Oeste Paulista Bauru. Técnico em Informática pelo CTI da Unesp. Graduado em Banco de Dados pela Fatec Bauru. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor do projeto Terminal de Informação, onde são postados tutoriais e notícias envolvendo o mundo da tecnologia.

Deixe uma resposta