Calcular digito verificador
Enviado: 01 Set 2022 19:20
Lá encima pegou a parte errada do manual, mas dá no mesmo.
Código: Selecionar todos
cValidar := Substr( cNumero, 1, 11 ) + ;
Substr( cNumero, 13, 11 ) + ;
Substr( cNumero, 25, 11 ) + ;
Substr( cNumero, 37, 11 )
cValidar := Substr( cValidar, 1, 3 ) + Substr( cValidar, 5 )
cDigito10 := DigitoDocPag10( cValidar )
cDigito11 := DigitoDocPag11( cValidar )
cDigito10F := CalculaDigito( cValidar, "10" )
cDigito11F := CalculaDigito( cValidar, "11" )
Código: Selecionar todos
cValidar := ""
FOR nCont = 1 TO 4
cParte := Substr( cNumero, ( nCont - 1 ) * 12 + 1, 12 )
cValidar += Left( cParte, 11 )
NEXT
Código: Selecionar todos
FUNCTION ValidDocPag( cNumero )
LOCAL cValidar, cDigito10, cDigito11, cDigito10F, cDigito11F, cParte, nCont
cValidar := ""
FOR nCont = 1 TO 4
cParte := Substr( cNumero, ( nCont - 1 ) * 12 + 1, 12 )
@ Row(), Col() SAY Right( cParte, 1 ) + " "
@ Row(), Col() SAY DigitoDocPag10( Left( cParte, 11 ) ) + " "
@ Row(), Col() SAY DigitoDocPag11( Left( cParte, 11 ) ) + " "
@ Row(), Col() SAY CalculaDigito( Left( cParte, 11 ), "10" ) + " "
@ Row(), Col() SAY CalculaDigito( Left( cParte, 11 ), "11" ) + " "
cValidar += Left( cParte, 11 )
NEXT
cValidar := Substr( cValidar, 1, 3 ) + Substr( cValidar, 5 )
cDigito10 := DigitoDocPag10( cValidar )
cDigito11 := DigitoDocPag11( cValidar )
cDigito10F := CalculaDigito( cValidar, "10" )
cDigito11F := CalculaDigito( cValidar, "11" )
@ Row(), Col() SAY cDigito10 + " "
@ Row(), Col() SAY cDigito11 + " "
@ Row(), Col() SAY cDigito10F + " "
@ Row(), Col() SAY cDigito11F + " "
RETURN Substr( cNumero, 4, 1 ) $ cDigito10 + cDigito11 + cDigito10F + cDigito11F
Por mais que você leia esse manual da Febraban, fica difícil fechar todas as possibilidades...836700000026 056100481003 222759467913 000343772000
Que tal acima? resto 1 então o dígito é zero.gilbertosilverio escreveu:Por mais que você leia esse manual da Febraban, fica difícil fechar todas as possibilidades...
Código: Selecionar todos
// Monta C¢digo de Barras (p/ Banco)
cDGCB := DC_Mod11(::cCodBco, 9, .T., ::cCodBco + ::cTipoMoeda + cFatorVenc + STRZERO(::nValor * 100, 10) + cCpoLivre)
cCodBar := ::cCodBco + ::cTipoMoeda + cDGCB + cFatorVenc + STRZERO(::nValor * 100, 10) + cCpoLivre
// 3 1 1 4 10 25
nY := 0
FOR nX := 1 TO LEN(cCodBar) STEP 2
::Merge(STRZERO(nY++, 2), SUBSTR(cCodBar, nX, 2))
NEXT
// Monta Representação Numérica do Código de Barras
cC1RN := ::cCodBco + ::cTipoMoeda + LEFT(cCpoLivre, 5)
cC1RN := cC1RN + DC_Mod10(::cCodBco, cC1RN)
cC2RN := SUBSTR(cCpoLivre, 6, 10)
cC2RN += DC_Mod10(::cCodBco, cC2RN)
cC3RN := SUBSTR(cCpoLivre, 16, 20)
cC3RN += DC_Mod10(::cCodBco, cC3RN)
cC4RN :=cDGCB
cC5RN :=cFatorVenc + STRZERO(::nValor * 100, 10)
cRNCB := LEFT(cC1RN, 5) + "." + SUBSTR(cC1RN, 6) + " " + LEFT(cC2RN, 5) + "." +;
SUBSTR(cC2RN, 6) + " " + LEFT(cC3RN, 5) + "." + SUBSTR(cC3RN, 6) + " " + cC4RN + " " + cC5RN
::Merge("LINDIG", cRNCB)
....
// Retorna Dígito de Controle Módulo 10 //
FUNCTION DC_Mod10( cCodBco, mNMOG )
LOCAL mVLDG, mSMMD, mCTDG, mRSDV, mDCMD
mSMMD:=0
FOR mCTDG := 1 TO LEN(mNMOG)
mVLDG := VAL(SUBSTR(mNMOG, LEN(mNMOG) - mCTDG + 1, 1)) * IF(MOD(mCTDG,2) == 0, 1, 2)
mSMMD += mVLDG - IF(mVLDG > 9, 9, 0)
NEXT
mRSDV := MOD(mSMMD, 10)
mDCMD := IF(mRSDV == 0, "0", STR(10 - mRSDV, 1))
RETURN mDCMD
/* -------------------------------------------------------------------------- */
// Retorna Digito de Controle Modulo 11 (p/ Banco) //
// bradesco -> DC_Mod11("237", 7, .F., carteira+agencia+nossonumero)
FUNCTION DC_Mod11( mCDBC, mBSDG, mFGCB, mNMOG, lMult10 )
LOCAL mSMMD, mCTDG, mSQMP, mRSDV, mDCMD
DEFAULT mFGCB TO .F., lMult10 TO .F.
mSMMD := 0
mSQMP := 2
FOR mCTDG := 1 TO LEN(mNMOG)
mSMMD += VAL(SUBSTR(mNMOG, LEN(mNMOG) - mCTDG + 1, 1)) * (mSQMP)
mSQMP := IF(mSQMP == mBSDG, 2, mSQMP+1)
NEXT
IF lMult10
mSMMD *= 10
ENDIF
mRSDV := MOD(mSMMD, 11)
IF mFGCB
mDCMD := IF(mRSDV > 9 .OR. mRSDV < 2, "1", STR(11 - mRSDV, 1))
ELSE
IF mCDBC == "001" // Brasil
mDCMD := IF(mRSDV == 0, "0", IF(mRSDV == 1, "X", STR(11 - mRSDV, 1)))
ELSEIF mCDBC like "(008|033|353)" //Santander Banespa
mDCMD := IF(mRSDV < 2, "0", IF(mRSDV == 10, "1", STR(11 - mRSDV, 1)))
//mDCMD := IF(mRSDV == 0, "0", IF(mRSDV == 1, "X", STR(11 - mRSDV, 1)))
ELSEIF mCDBC=="104" // Caixa
mRSDV := 11 - mRSDV
mDCMD := IF(mRSDV > 9, "0", STR(mRSDV, 1))
ELSEIF mCDBC == "237" // Bradesco
mDCMD := IF(mRSDV == 0, "0", IF(mRSDV == 1, "P", STR(11 - mRSDV, 1)))
ELSEIF mCDBC == "341" // Itau
mDCMD := IF(mRSDV == 11, "1", STR(11 - mRSDV, 1))
ELSEIF mCDBC == "409" // Unibanco
mDCMD := IF(mRSDV == 0 .OR. mRSDV == 10, "0", STR(mRSDV, 1))
ELSEIF mCDBC == "422" // Safra
mDCMD := IF(mRSDV==0, "1", IF(mRSDV == 1, "0", STR(11 - mRSDV, 1)))
ENDIF
ENDIF
RETURN mDCMD
/* -------------------------------------------------------------------------- */
// Retorna Dígito de Controle Módulo Especial //
FUNCTION DC_ModEsp( cCodBco, mNMOG )
LOCAL mVLDG, mSMMD, mCTDG, mSQMP, mRSDV, mDCMD:=0
IF cCodBco == "033" // Banespa
mSMMD:=0
mSQMP:=3
FOR mCTDG := 1 TO LEN(mNMOG)
mVLDG := VAL(SUBSTR(mNMOG, LEN(mNMOG) - mCTDG + 1, 1)) * (mSQMP)
mSMMD += mVLDG - (INT(mVLDG / 10) * 10)
mSQMP := IF(mSQMP == 3, 7, IF(mSQMP == 7, 9, IIF(mSQMP == 9, 1, 3)))
NEXT
mRSDV := mSMMD - (INT(mSMMD / 10) * 10)
mDCMD := IIF(mRSDV == 0, 0, 10 - mRSDV)
ENDIF
RETURN str(mDCMD,1)
Não sei se pensou nisto, mas ....gilbertosilverio escreveu:Analisando o código do harbourboleto, observei que cada banco tem sua forma de calculo da mod11, creio que seja o mesmo para esses pagamentos a concessionarias, cada qual "inventa" sua maneira, e realmente uma Torre de Babel, cada um fala uma língua.
Portanto, creio que para conseguir fazer funcionar e necessário analisar caso a caso...
Código: Selecionar todos
PROCEDURE Main
LOCAL cAgua := "82630000000565760097914034812984770196266947635"
LOCAL cLuz := "83680000001762320048100942155127816001453291153"
LOCAL cTelefone := "84610000000510140082089699479218581554719226099"
IF Modulo11( "34191000000000000001753980229122525005423000" ) != "1"
? 'Função modulo11 está com erro!"
ENDIF
IF Modulo10( "399903512" ) != "8"
? "Função modulo10 está com erro!"
ENDIF
? LinhaToBarra( cAgua )
? LinhaToBarra( cLuz )
? LinhaToBarra( cTelefone )
Inkey(0)
RETURN
FUNCTION LinhaToBarra( linha )
LOCAL Barra
barra = Substr( linha, 1, 4 ) + ;
Substr( linha, 33, 15 ) + ;
Substr( linha, 5, 5 ) + ;
Substr( linha, 11, 10 ) + ;
Substr( linha, 22, 10 )
IF Modulo11( Substr( barra, 1, 4 ) + Substr( barra, 6, 39 ) ) != Substr( barra, 5, 1 )
? "Digito verificador invalido"
ENDIF
RETURN barra
FUNCTION BarraToLinha( barra )
LOCAL Campo1, Campo2, Campo3, Campo4, Campo5, Linha
Campo1 := Substr( barra, 1, 4 ) + Substr( barra, 20, 1 ) + Substr( barra, 21, 4 )
Campo2 := Substr( barra, 25, 5 ) + Substr( Barra, 25 + 5, 5 )
Campo3 := Substr( Barra, 35, 5 ) + Substr( Barra, 35 + 5, 5 )
Campo4 := Substr( Barra, 5, 1 )
Campo5 := Substr( Barra, 6, 14 )
IF Modulo11( Substr( Barra, 1, 4 ) + Substr( Barra, 6, 99 ) ) != campo4
? "Digito invalido"
ENDIF
Linha := Campo1 + Modulo10( campo1 ) + ;
Campo2 + Modulo10( campo2 ) + ;
Campo3 + Modulo10( campo3 ) + ;
Campo4 + Campo5
RETURN Linha
STATIC FUNCTION Modulo10( cNumero )
LOCAL cChar, nSoma := 0, nValor, nResto, cDigito
FOR EACH cChar IN cNumero DESCEND
nValor := Val( cChar ) * iif( mod( cChar:__EnumIndex, 2 ) == 0, 1, 2 )
nSoma += nValor - iif( nValor > 9, 9, 0 )
NEXT
nResto := MOD( nSoma, 10 )
cDigito := Str( iif( nResto == 0, 0, 10 - nResto ), 1 )
RETURN cDigito
STATIC FUNCTION Modulo11( cNumero )
LOCAL cChar, nSoma := 0, nResto, cDigito, nMultiplica := 2
cNumero := AllTrim( cNumero )
FOR EACH cChar IN cNumero DESCEND
nSoma += Val( cChar ) * nMultiplica
nMultiplica := iif( nMultiplica == 9, 2, nMultiplica + 1 )
NEXT
nResto := Mod( nSoma, 11 )
cDigito := Str( iif( nResto == 0, 1, iif( nResto == 1, 0, 11 - nResto ) ), 1 )
RETURN cDigito