Clique para saber mais...
  Home     Download     Produtos / Cursos     Revista     Vídeo Aulas     Fórum     Contato   Clique aqui para logar | 14 de Agosto de 2026
  Login

Codinome
Senha
Salvar informações

 Esqueci minha senha
 Novo Cadastro

  Usuários
148 Usuários Online

  Revista ActiveDelphi
 Assine Já!
 Edições
 Sobre a Revista

  Conteúdo
 Apostilas
 Artigos
 Componentes
 Dicas
 News
 Programas / Exemplos
 Vídeo Aulas

  Serviços
 Active News
 Fórum
 Produtos / Cursos

  Outros
 Colunistas
 Contato
 Top 10

  Publicidade

  [Artigos]  Cálculo do Dígito Verificador da Chave de Acesso do CT-e
Publicado por ggiovanii : Segunda, Dezembro 20, 2010 - 11:37 GMT-3 (984 leituras)
Comentários 3 Comentários   Enviar esta notícia a um amigo Enviar para um amigo   Versão para Impressão Versão para impressão
Bruno Caltran Olá pessoal! Neste artigo demonstrarei como realizar o cálculo do dígito verificador da chave de acesso do CT-e. Antes de demonstrar como gerar o digito verificador, vamos entender do que é composta a chave de acesso.

A Chave de Acesso do Conhecimento de Transporte Eletrônico é representada por uma seqüência de 44 caracteres numéricos, representados da seguinte forma:

Código da UF - Código da UF do emitente do Documento Fiscal (Tamanho 2 caracteres)
Ano e Mês da Emissão (AAMM) - Ano e Mês de emissão do CT-e (Tamanho 4 caracteres)
CNPJ - CNPJ do emitente (Tamanho 14 caracteres)
Modelo - Modelo do Documento Fiscal (Tamanho 2 caracteres)
Série - Série do Documento Fiscal (Tamanho 3 caracteres)
Numero do CTe - Número do Documento Fiscal (Tamanho 9 caracteres)
Código Numérico - Código Numérico que compõe a Chave de Acesso (Tamanho 9 caracteres)
Digito - Dígito Verificador da Chave de Acesso (Tamanho 1 caractere)

 

O Cálculo

O dígito verificador da chave de acesso do CT-e é baseado em um cálculo do módulo 11. O módulo 11 de um número é calculado multiplicando-se cada algarismo pela seqüência de multiplicadores 2,3,4,5,6,7,8,9,2,3, ... posicionados da direita para a esquerda.

A somatória dos resultados das ponderações dos algarismos é dividida por 11 e o DV (dígito verificador) será a diferença entre o divisor (11) e o resto da divisão:

DV = 11 - (resto da divisão)

Quando o resto da divisão for 0 (zero) ou 1 (um), o DV deverá ser igual a 0 (zero).

Vamos exemplificar toda essa teoria no Delphi.

Primeiro devemos desenhar o formulário. Nesse exemplo estou utilizando dois edit’s para exemplificar melhor o funcionamento, porém em seu projeto poderá realizar tudo no mesmo Edit. Coloquei também um botão para acionar o evento do cálculo quando clicar. Veja como ficou a interface na figura 1:


Figura 1 - Interface da aplicação de exemplo

O primeiro Edit vamos chamá-lo de edtChave. O segundo Edit, de edtDV.

No edtChave, vamos informar uma chave de exemplo, retirada da página 74 do Manual de Integração – Contribuinte Padrões Técnicos de Comunicação.

Chave Exemplo: 5206043300991100250655012000000780026730161. O dígito verificador dessa chave deverá ser igual à “5”

Agora vamos ao código do botão.  O algoritmo foi montada de forma bem primária para facilitar o entendimento, mas lembre-se que você pode usar arrays para facilitar:

procedure TForm1.btnGerarDigitoClick(Sender: TObject);
Var
  // Essas serão as variáveis responsáveis por armazenar cada numero da chave
  V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17,
    V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32,
    V33, V34, V35, V36, V37, V38, V39, V40, V41, V42, V43: Real;
 
  // as variáveis abaixo serão responsáveis por armazenar os resultados
  //das multiplicações
  R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17,
    R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32,
    R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43: Real;
 
  // Utilizaremos as variáveis abaixo para formulação do resultado
  Soma, Divisao, Resultado: Real;
  SomaI: integer;
begin
  // Através do código abaixo, vamos separar os valores com a “função Copy”
  //da chave de acesso
  V1 := StrToFloat(Copy(edtChaveAcesso.Text, 1, 1));
  V2 := StrToFloat(Copy(edtChaveAcesso.Text, 2, 1));
  V3 := StrToFloat(Copy(edtChaveAcesso.Text, 3, 1));
  V4 := StrToFloat(Copy(edtChaveAcesso.Text, 4, 1));
  V5 := StrToFloat(Copy(edtChaveAcesso.Text, 5, 1));
  V6 := StrToFloat(Copy(edtChaveAcesso.Text, 6, 1));
  V7 := StrToFloat(Copy(edtChaveAcesso.Text, 7, 1));
  V8 := StrToFloat(Copy(edtChaveAcesso.Text, 8, 1));
  V9 := StrToFloat(Copy(edtChaveAcesso.Text, 9, 1));
  V10 := StrToFloat(Copy(edtChaveAcesso.Text, 10, 1));
  V11 := StrToFloat(Copy(edtChaveAcesso.Text, 11, 1));
  V12 := StrToFloat(Copy(edtChaveAcesso.Text, 12, 1));
  V13 := StrToFloat(Copy(edtChaveAcesso.Text, 13, 1));
  V14 := StrToFloat(Copy(edtChaveAcesso.Text, 14, 1));
  V15 := StrToFloat(Copy(edtChaveAcesso.Text, 15, 1));
  V16 := StrToFloat(Copy(edtChaveAcesso.Text, 16, 1));
  V17 := StrToFloat(Copy(edtChaveAcesso.Text, 17, 1));
  V18 := StrToFloat(Copy(edtChaveAcesso.Text, 18, 1));
  V19 := StrToFloat(Copy(edtChaveAcesso.Text, 19, 1));
  V20 := StrToFloat(Copy(edtChaveAcesso.Text, 20, 1));
  V21 := StrToFloat(Copy(edtChaveAcesso.Text, 21, 1));
  V22 := StrToFloat(Copy(edtChaveAcesso.Text, 22, 1));
  V23 := StrToFloat(Copy(edtChaveAcesso.Text, 23, 1));
  V24 := StrToFloat(Copy(edtChaveAcesso.Text, 24, 1));
  V25 := StrToFloat(Copy(edtChaveAcesso.Text, 25, 1));
  V26 := StrToFloat(Copy(edtChaveAcesso.Text, 26, 1));
  V27 := StrToFloat(Copy(edtChaveAcesso.Text, 27, 1));
  V28 := StrToFloat(Copy(edtChaveAcesso.Text, 28, 1));
  V29 := StrToFloat(Copy(edtChaveAcesso.Text, 29, 1));
  V30 := StrToFloat(Copy(edtChaveAcesso.Text, 30, 1));
  V31 := StrToFloat(Copy(edtChaveAcesso.Text, 31, 1));
  V32 := StrToFloat(Copy(edtChaveAcesso.Text, 32, 1));
  V33 := StrToFloat(Copy(edtChaveAcesso.Text, 33, 1));
  V34 := StrToFloat(Copy(edtChaveAcesso.Text, 34, 1));
  V35 := StrToFloat(Copy(edtChaveAcesso.Text, 35, 1));
  V36 := StrToFloat(Copy(edtChaveAcesso.Text, 36, 1));
  V37 := StrToFloat(Copy(edtChaveAcesso.Text, 37, 1));
  V38 := StrToFloat(Copy(edtChaveAcesso.Text, 38, 1));
  V39 := StrToFloat(Copy(edtChaveAcesso.Text, 39, 1));
  V40 := StrToFloat(Copy(edtChaveAcesso.Text, 40, 1));
  V41 := StrToFloat(Copy(edtChaveAcesso.Text, 41, 1));
  V42 := StrToFloat(Copy(edtChaveAcesso.Text, 42, 1));
  V43 := StrToFloat(Copy(edtChaveAcesso.Text, 43, 1));
 
  // Conforme explicado anteriormente neste artigo, faremos a multiplicação
  // por  2,3,4,....9
  R43 := V43 * 2;
  R42 := V42 * 3;
  R41 := V41 * 4;
  R40 := V40 * 5;
  R39 := V39 * 6;
  R38 := V38 * 7;
  R37 := V37 * 8;
  R36 := V36 * 9;
  R35 := V35 * 2;
  R34 := V34 * 3;
  R33 := V33 * 4;
  R32 := V32 * 5;
  R31 := V31 * 6;
  R30 := V30 * 7;
  R29 := V29 * 8;
  R28 := V28 * 9;
  R27 := V27 * 2;
  R26 := V26 * 3;
  R25 := V25 * 4;
  R24 := V24 * 5;
  R23 := V23 * 6;
  R22 := V22 * 7;
  R21 := V21 * 8;
  R20 := V20 * 9;
  R19 := V19 * 2;
  R18 := V18 * 3;
  R17 := V17 * 4;
  R16 := V16 * 5;
  R15 := V15 * 6;
  R14 := V14 * 7;
  R13 := V13 * 8;
  R12 := V12 * 9;
  R11 := V11 * 2;
  R10 := V10 * 3;
  R9 := V9 * 4;
  R8 := V8 * 5;
  R7 := V7 * 6;
  R6 := V6 * 7;
  R5 := V5 * 8;
  R4 := V4 * 9;
  R3 := V3 * 2;
  R2 := V2 * 3;
  R1 := V1 * 4;
 
  // Somaremos os valores obtidos dos resultados das multiplicações
  Soma := R1 + R2 + R3 + R4 + R5 + R6 + R7 + R8 + R9 + R10 + R11 + R12 + R13 +
    R14 + R15 + R16 + R17 + R18 + R19 + R20 + R21 + R22 + R23 + R24 + R25 +
    R26 + R27 + R28 + R29 + R30 + R31 + R32 + R33 + R34 + R35 + R36 + R37 +
    R38 + R39 + R40 + R41 + R42 + R43;
 
  SomaI := Trunc(Soma);
  Divisao := (SomaI mod 11);
  Resultado := 11 - Divisao;
 
  // Compara se o resultado é igual a 1 (Se for deverá ser = 0)
  if Resultado = 1 then
    edtDV.Text := '0'
  else
    edtDV.Text := FloatToStr(Resultado);
end;

Pronto!! Agora é só adaptar o algoritmo ao seu projeto. Para customizar e reduzir o tamanho do código, você poderá utilizar arrays para alimentação das variáveis e multiplicação dos resultados.

Um grade abraço e até o próximo artigo!

Por: Bruno Giovani Caltran
Contato: bruno@pirabyte.com.br |
Twitter: http://twitter.com/bgcaltran
Blog: http://bgcaltran.blogspot.com



Comentários Comentários
   Ordem:  
Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos.


por: gilsonnrodrigues (gilsonnr@hotmail.com) : Dez 22, 2010 - 08:56
(Informações sobre o membro | Enviar uma mensagem) http://
procedure TForm1.btnGerarDigitoClick(Sender: TObject);
Var
I, Soma, Peso : integer;
S : string;
begin
S := edtChaveAcesso.Text;
Soma := 0
Peso := 9;
for I := Length(S) downto 1 do
begin
if Peso = 9 then
Peso := 2
else
Inc(Peso);

Inc(Soma, P * (Ord(S[1]) - 48) * P);
end;

Soma := 11 - (Soma mod 11);

// Compara se o resultado é igual a 1 (Se for deverá ser = 0)
if Soma = 1 then //e se for 11 ou 10?
edtDV.Text := '0'
else
edtDV.Text := Char(Soma + 48);
end;


por: VSF (hereim@ig.com.br) : Dez 22, 2010 - 04:30
(Informações sobre o membro | Enviar uma mensagem) http://www.igara.com.br/victory
Segue sugestão otimizada e já colocada em formato de função! Pronta para colocar direto na sua aplicação sem grande adaptações. Função removida do produto Assinatura32dll.dll disponível em http://www.igara.com.br/produto.php?cod_produto=121

Os comentários no cabeçalho estão de acordo com o sistema DelphiCodeToDoc de geração de documentação automática para Delphi.


{*------------------------------------------------------------------------------
Calcula Dígito Verificador da Chave de Acesso
O Dígito Verificador (DV) garante a integridade da chave de acesso através de cálculo de Módulo 11

@Author Victory Fernandes
@Version 16/12/2008 Última alteração por Victory Fernandes

@param sChave Chave de acesso exceto campo DV. 43 caracteres.

@return Dígito Verificador da Chave de Acesso (1 caracter) calculado conforme formato descrito no Manual de Integração disponibilizado no portal oficial da NFe em www.nfe.fazenda.gov.br
-------------------------------------------------------------------------------}
function fncDVNFe(sChave: PChar): PChar; SafeCall; export;
var
wValor : WideString;
Soma : integer;
Cont, Peso, Digito, resto : integer;
Base: Integer;
begin
wValor := sChave;
Soma := 0;
Peso := 2;
Base := 9;

for Cont := Length(wValor) downto 1 do
begin
Soma := Soma + (StrToInt(wValor[Cont]) * Peso);
if Peso < Base then
Peso := Peso + 1
else
Peso := 2;
end;

resto := (Soma mod 11);

//Conforme o manual se resto = 0 ou 1 então DV=0
//Exemplo de chave de NFe onde resto = 0 2508120316848800015955001000113334166660521
if (resto = 0) or (resto = 1) then
Digito := 0
else
Digito := 11 - (Soma mod 11);

Result := PChar(IntToStr(Digito));
end;


por: marcosspirito (marcosspirito_2@hotmail.com) : Fev 27, 2013 - 09:01
(Informações sobre o membro | Enviar uma mensagem)
Acredito que numa função que retorne True ou False
caso a chave esteja correta é mais fácil trabalhar, segue abaixo

function TFrmConhecimentos.ValidaChaveCTe(Chave: String): Boolean;
Var
V,R: Array[1..43] of Integer;
I,X,Soma:Integer;
begin
Result:=False;
if Length(Chave) < 44 then Exit;
try
X:=2;
Soma:=0;
for I:=1 to 43 do
V[I] := StrToInt(Chave[I]);
for I:=43 downto 1 do
begin
R[I] := V[I] * X;
Soma := Soma + R[I];
if (X=9) then X:=2 else Inc(X);
end;
Soma := 11 - (Soma mod 11);
if (Soma = 1) then Soma := 0;
Result := IntToStr(Soma)=Chave[44];
Except
Result:=False;
end;
end;
  Edição 112

Revista ActiveDelphi

  50 Programas Fontes


  Produtos

Conheça Nossos Produtos

Copyright© 2001-2016 – Active Delphi – Todos os direitos reservados