Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
How to incorporate charts on reports
Message
From
01/12/2006 15:01:56
 
 
To
01/12/2006 11:11:07
General information
Forum:
Visual FoxPro
Category:
Reports & Report designer
Environment versions
Visual FoxPro:
VFP 6
OS:
Windows 2000
Database:
Visual FoxPro
Miscellaneous
Thread ID:
01174029
Message ID:
01174247
Views:
7
Códigos de barra en reportes de Visual FoxPro lecturas 110137

Enviado por Luis María Guayán en Viernes, 16 Febrero, 2001
Ahora podemos imprimir códigos de barra en nuestros reportes.

Códigos de barra en reportes de Visual FoxPro
Por Luis María Guayán, Tucumán, Argentina


--------------------------------------------------------------------------------

Actualizaciones de este artículo:
2002/04/08 - Corrección del código 128
2002/08/10 - Añadido código Interleaved 2 of 5
2002/08/14 - Nuevas fuentes True Type
2004/09/15 - Añadido código Interleaved 2 of 5 con lectura humana
2005/05/05 - Ejemplo de informes para descarga

Contenido
En este documento se describe la forma de añadir códigos de barra a los reportes de Visual FoxPro, para su impresión con fuentes True Type. Los códigos de barra tratados aquí son los siguientes:

Código 39
Código 128
EAN-13
EAN-8
Interleaved 2 of 5
Para lograr esto, aparte de las fuentes True Type, se necesitan funciones definidas por el usuario en VFP, que conviertan el texto a codificar en el formato adecuado según cada código y cada fuente True Type. Las fuentes True Type y las funciones se encuentran mas abajo y pueden ser descargadas.

Al final del documento se encuentran ejemplos de uso de las funciones, una muestra de los resultados obtenidos en reportes de VFP, y notas para su mejor implementación. También se adjunta un ejemplo en VFP con dos informes para su descarga.

Códigos de Barra
Solo haremos una breve descripción de cada uno de los posibles códigos, para elegir el mas adecuado para la aplicación que vamos a implementar.

Código 39
Este código es de longitud variable, cuya limitación en el largo la da el espacio disponible para imprimir y la capacidad del lector de código de barra que usaremos.

El juego de caracteres del código 39 incluye 43 caracteres: los dígitos 0-9, las letras A-Z (mayúscula solamente), el espacio y los siguientes símbolos: - + . $ / *. El "*" es el carácter de inicio y final del código, por lo que no deberá usarse en un texto a codificar.

Cada caracter se compone de 5 barras y 4 espacios. 3 de estos 9 elementos son anchos (de allí el nombre "3 de 9") y 6 angostos.

El código 39 se forma de la siguiente manera:

Start + Cadena + EndCódigo 128
Este también es un código de longitud variable, y menos largo que el código 39.

El código 128 incluye los dígito 0-9, letras A-Z (mayúsculas y minúsculas), y todos los caracteres estándares ASCII (en total 128 caracteres, de allí su nombre).

El código 128 se divide en tres subconjuntos A, B, y C.

El subconjunto A incluye: los dígitos, las letras mayúsculas, y los códigos de control.
El subconjunto B incluye: los dígitos, las letras mayúsculas y minúsculas, y los códigos de control.
El subconjunto C incluye: solo los dígitos y comprime dos dígitos numéricos en cada carácter, proporcionando una densidad excelente.
Este código tiene un dígito de control que ofrece mas seguridad en la lectura. Dicho dígito de control se calcula con el siguiente algoritmo:

* Valor de inicio del subconjunto A = 203
* Valor de inicio del subconjunto B = 204
* Valor de inicio del subconjunto C = 205
* Valor de final de todos los subconjuntos = 206
Suma = valor del caracter de inicio del subconjunto
Por cada caracter a codificar
Suma = Suma + (valor de cada caracter * posicion)
Final de los caracteres
Dígito de control = módulo 103 de SumaLos códigos 128 se forman de la siguiente manera:

Start + Cadena + Check_Digit + EndCódigo EAN-13 y EAN-8 (European Article Numbering)
El EAN-13 se utiliza por todo el mundo para las mercaderías de venta al por menor. Es de longitud fija (13 caracteres). El EAN-8 es una versión acortada del código EAN-13 e incluye solo 8 caracteres.

Estos códigos los asigna y controla EAN International (http://www.ean.be) y las entidades autorizadas por EAN en cada país.

En el código Ean-13, los primeros 6 dígitos representan el país y la empresa, los siguientes 6 dígitos representan el producto, y el restante es el dígito de control. Aparte del país, los primeros dos o tres dígitos pueden representar por ejemplo: libros (ISBN), periódicos (ISSN), usos internos, etc.

En el código Ean-8, los primeros 4 dígitos representan el país y la empresa, los siguientes 3 dígitos representan el producto, y el restante es el dígito de control.

El dígito de control se calcula con el siguiente algoritmo:

Suma = 0
Por cada uno de los 12 ó 7 dígitos a codificar
Valor corrector = 1 si la posición del dígito es impar
= 3 si la posición es par
Suma = Suma + Valor del dígito * Valor corrector
Final de los dígitos
Digito de control = 10 - módulo 10 de Suma
Si Digito de control = 10
Digito de control = 0
Final SiLos códigos EAN se forman de la siguiente manera:

Código_País + Código_Empresa + Codigo_Artículo + Check_DigitCódigo Interleaved 2 of 5
Este es un código de longitud variable, al igual que los códigos 39 y 128.

El Interleaved 2 of 5 incluye solamente los dígitos numéricos [0..9] y comprime dos dígitos numéricos en cada carácter, proporcionando una muy buena densidad. Todos los códigos Interleaved 2 of 5 tienen una cantidad par de dígitos.

Cada par de dígitos, se codifica en un caracter formado por una serie de 5 barras y 5 espacios. 2 de cada 5 barras son anchas, de allí el nombre "2 of 5".

Este código tiene un dígito de control que ofrece mas seguridad en la lectura. Dicho dígito de control se calcula con el siguiente algoritmo:

Suma = 0
Por cada uno de los dígitos a codificar
Valor corrector = 1 si la posición del dígito es impar
= 3 si la posición es par
Suma = Suma + Valor del dígito * Valor corrector
Final de los dígitos
Digito de control = 10 - módulo 10 de Suma
Si Digito de control = 10
Digito de control = 0
Final SiLos códigos Interleaved 2 of 5 se forman de la siguiente manera:

Start + Cadena + Check_Digit + EndFuentes True Type
Las fuentes True Type que se usan en estos ejemplo, son archivos freeware y funcionan perfectamente con las funciones para VFP descritas mas abajo.

A las fuentes utilizadas se las puede descargar de: fuentes.zip (30,9 Kb.)

Para una mejor impresión y lectura de los códigos, se aconseja utilizar los tamaños de fuentes que a continuación se detallan:

Fuente True Type Archivo Tamaño
PF Barcode 39 PF_C39.ttf 20 ó 22
PF Barcode 128 PF_C128.ttf 22, 24, 26 ó 28
PF EAN P36 PF_EAN_P36.ttf 36
PF EAN P72 PF_EAN_P72.ttf 72
PF Interleaved 2 of 5 PF_I2OF5.ttf 36 ó 48
PF Interleaved 2 of 5 Wide PF_I2OF5_W.ttf 28 ó 36
PF Interleavev 2 of 5 Text PF_I2OF5_Text.ttf 28 ó 36

Funciones en VFP
A continuación se detallan las funciones en VFP que transforman un texto al formato de código de barra elegido.

Estas funciones se las puede descargar de: funcion.zip (2,2 Kb.)
*------------------------------------------------------
* FUNCTION _StrTo39(tcString) * CODIGO 39
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF Barcode 39"
* USO: _StrTo39('Codigo 39')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrTo39(tcString)
  LOCAL lcRet
  lcRet = '*' + tcString + '*'
  RETURN lcRet
ENDFUNC
*------------------------------------------------------
* FUNCTION _StrTo128A(tcString) * CODIGO 128A
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF Barcode 128"
* Caracteres numéricos y alfabeticos (solo mayúsculas)
* Si un caracter es no válido lo remplaza por espacio
* USO: _StrTo128A('CODIGO 128 A')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrTo128A(tcString)
  LOCAL lcStart, lcStop, lcRet, lcCheck, ;
    lnLong, lnI, lnCheckSum, lnAsc
  lcStart = CHR(103 + 32)
  lcStop = CHR(106 + 32)
  lnCheckSum = ASC(lcStart) - 32
  lcRet = tcString
  lnLong = LEN(lcRet)
  FOR lnI = 1 TO lnLong
    lnAsc = ASC(SUBS(lcRet,lnI,1)) - 32
    IF NOT BETWEEN(lnAsc,0,64)
      lcRet = STUFF(lcRet,lnI,1,CHR(32))
      lnAsc = ASC(SUBS(lcRet,lnI,1)) - 32
    ENDIF
    lnCheckSum = lnCheckSum + (lnAsc * lnI)
  ENDFOR
  lcCheck = CHR(MOD(lnCheckSum,103) + 32)
  lcRet = lcStart + lcRet + lcCheck + lcStop
  *--- Esto es para cambiar los espacios y caracteres invalidos
  lcRet = STRTRAN(lcRet,CHR(32),CHR(232))
  lcRet = STRTRAN(lcRet,CHR(127),CHR(192))
  lcRet = STRTRAN(lcRet,CHR(128),CHR(193))
  RETURN lcRet
ENDFUNC
*------------------------------------------------------
* FUNCTION _StrTo128B(tcString) * CODIGO 128B
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF Barcode 128"
* Caracteres numéricos y alfabeticos (mayúsculas y minúsculas)
* Si un caracter es no válido lo remplaza por espacio
* USO: _StrTo128B('Codigo 128 B')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrTo128B(tcString)
  LOCAL lcStart, lcStop, lcRet, lcCheck, ;
    lnLong, lnI, lnCheckSum, lnAsc
  lcStart = CHR(104 + 32)
  lcStop = CHR(106 + 32)
  lnCheckSum = ASC(lcStart) - 32
  lcRet = tcString
  lnLong = LEN(lcRet)
  FOR lnI = 1 TO lnLong
    lnAsc = ASC(SUBS(lcRet,lnI,1)) - 32
    IF NOT BETWEEN(lnAsc,0,99)
      lcRet = STUFF(lcRet,lnI,1,CHR(32))
      lnAsc = ASC(SUBS(lcRet,lnI,1)) - 32
    ENDIF
    lnCheckSum = lnCheckSum + (lnAsc * lnI)
  ENDFOR
  lcCheck = CHR(MOD(lnCheckSum,103) + 32)
  lcRet = lcStart + lcRet + lcCheck + lcStop
  *--- Esto es para cambiar los espacios y caracteres invalidos
  lcRet = STRTRAN(lcRet,CHR(32),CHR(232))
  lcRet = STRTRAN(lcRet,CHR(127),CHR(192))
  lcRet = STRTRAN(lcRet,CHR(128),CHR(193))
  RETURN lcRet
ENDFUNC
*------------------------------------------------------
* FUNCTION _StrTo128C(tcString) * CODIGO 128C
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF Barcode 128"
* Solo caracteres numéricos
* USO: _StrTo128C('1234567890')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrTo128C(tcString)
  LOCAL lcStart, lcStop, lcRet, lcCheck, lcCar, ;
    lnLong, lnI, lnCheckSum, lnAsc
  lcStart = CHR(105 + 32)
  lcStop = CHR(106 + 32)
  lnCheckSum = ASC(lcStart) - 32
  lcRet = ALLTRIM(tcString)
  lnLong = LEN(lcRet)
  *--- La longitud debe ser par
  IF MOD(lnLong,2) # 0
    lcRet = '0' + lcRet
    lnLong = LEN(lcRet)
  ENDIF
  *--- Convierto los pares a caracteres
  lcCar = ''
  FOR lnI = 1 TO lnLong STEP 2
    lcCar = lcCar + CHR(VAL(SUBS(lcRet,lnI,2)) + 32)
  ENDFOR
  lcRet = lcCar
  lnLong = LEN(lcRet)
  FOR lnI = 1 TO lnLong
    lnAsc = ASC(SUBS(lcRet,lnI,1)) - 32
    lnCheckSum = lnCheckSum + (lnAsc * lnI)
  ENDFOR
  lcCheck = CHR(MOD(lnCheckSum,103) + 32)
  lcRet = lcStart + lcRet + lcCheck + lcStop
  *--- Esto es para cambiar los espacios y caracteres invalidos
  lcRet = STRTRAN(lcRet,CHR(32),CHR(232))
  lcRet = STRTRAN(lcRet,CHR(127),CHR(192))
  lcRet = STRTRAN(lcRet,CHR(128),CHR(193))
  RETURN lcRet
ENDFUNC
*------------------------------------------------------
* FUNCTION _StrToEan13(tcString,.T.) * CODIGO EAN-13
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF EAN P36" ó "PF EAN P72"
* PARAMETROS:
*   tcString: Caracter de 12 dígitos (0..9)
*   tlCheckD: .T. Solo genera el dígito de control
*             .F. Genera dígito y caracteres a imprimir
* USO: _StrToEan13('123456789012')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrToEan13(tcString,tlCheckD)
  LOCAL lcLat, lcMed, lcRet, lcJuego, ;
    lcIni, lcResto, lcCod, lnI, ;
    lnCheckSum, lnAux, laJuego(10), lnPri
  lcRet = ALLTRIM(tcString)
  IF LEN(lcRet) # 12
    *--- Error en parámetro
    *--- debe tener un largo = 12
    RETURN ''
  ENDIF
  *--- Genero dígito de control
  lnCheckSum = 0
  FOR lnI = 1 TO 12
    IF MOD(lnI,2) = 0
      lnCheckSum = lnCheckSum + VAL(SUBS(lcRet,lnI,1)) * 3
    ELSE
      lnCheckSum = lnCheckSum + VAL(SUBS(lcRet,lnI,1)) * 1
    ENDIF
  ENDFOR
  lnAux = MOD(lnCheckSum,10)
  lcRet = lcRet + ALLTRIM(STR(IIF(lnAux = 0,0,10-lnAux)))
  IF tlCheckD
    *--- Si solo genero dígito de control
    RETURN lcRet
  ENDIF
  *--- Para imprimir con fuente True Type PF_EAN_PXX
  *--- 1er. dígito (lnPri)
  lnPri = VAL(LEFT(lcRet,1))
  *--- Tabla de Juegos de Caracteres
  *--- según 'lnPri' (¡NO CAMBIAR!)
  laJuego(1) = 'AAAAAACCCCCC'   && 0
  laJuego(2) = 'AABABBCCCCCC'   && 1
  laJuego(3) = 'AABBABCCCCCC'   && 2
  laJuego(4) = 'AABBBACCCCCC'   && 3
  laJuego(5) = 'ABAABBCCCCCC'   && 4
  laJuego(6) = 'ABBAABCCCCCC'   && 5
  laJuego(7) = 'ABBBAACCCCCC'   && 6
  laJuego(8) = 'ABABABCCCCCC'   && 7
  laJuego(9) = 'ABABBACCCCCC'   && 8
  laJuego(10) = 'ABBABACCCCCC'   && 9
  *--- Caracter inicial (fuera del código)
  lcIni = CHR(lnPri + 35)
  *--- Caracteres lateral y central
  lcLat = CHR(33)
  lcMed = CHR(45)
  *--- Resto de los caracteres
  lcResto = SUBS(lcRet,2,12)
  FOR lnI = 1 TO 12
    lcJuego = SUBS(laJuego(lnPri + 1),lnI,1)
    DO CASE
      CASE lcJuego = 'A'
        lcResto = STUFF(lcResto,lnI,1,CHR(VAL(SUBS(lcResto,lnI,1)) + 48))
      CASE lcJuego = 'B'
        lcResto = STUFF(lcResto,lnI,1,CHR(VAL(SUBS(lcResto,lnI,1)) + 65))
      CASE lcJuego = 'C'
        lcResto = STUFF(lcResto,lnI,1,CHR(VAL(SUBS(lcResto,lnI,1)) + 97))
    ENDCASE
  ENDFOR
  *--- Armo código
  lcCod = lcIni + lcLat + SUBS(lcResto,1,6) + lcMed + ;
  	SUBS(lcResto,7,6) + lcLat
  RETURN lcCod
ENDFUNC
*------------------------------------------------------
* FUNCTION _StrToEan8(tcString,.T.) * CODIGO EAN-8
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF EAN P36" ó "PF EAN P72"
* PARAMETROS:
*   tcString: Caracter de 7 dígitos (0..9)
*   tlCheckD: .T. Solo genera el dígito de control
*             .F. Genera dígito y caracteres a imprimir
* USO: _StrToEan8('1234567')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrToEan8(tcString,tlCheckD)
  LOCAL lcLat, lcMed, lcRet, ;
    lcIni, lcCod, lnI, ;
    lnCheckSum, lnAux
  lcRet = ALLTRIM(tcString)
  IF LEN(lcRet) # 7
    *--- Error en parámetro
    *--- debe tener un largo = 7
    RETURN ''
  ENDIF
  *--- Genero dígito de control
  lnCheckSum = 0
  FOR lnI = 1 TO 7
    IF MOD(lnI,2) = 0
      lnCheckSum = lnCheckSum + VAL(SUBS(lcRet,lnI,1)) * 3
    ELSE
      lnCheckSum = lnCheckSum + VAL(SUBS(lcRet,lnI,1)) * 1
    ENDIF
  ENDFOR
  lnAux = MOD(lnCheckSum,10)
  lcRet = lcRet + ALLTRIM(STR(IIF(lnAux = 0,0,10-lnAux)))
  IF tlCheckD
    *--- Si solo genero dígito de control
    RETURN lcRet
  ENDIF
  *--- Para imprimir con fuente True Type PF_EAN_PXX
  *--- Caracteres lateral y central
  lcLat = CHR(33)
  lcMed = CHR(45)
  *--- Caracteres
  FOR lnI = 1 TO 8
    IF lnI <= 4
      lcRet = STUFF(lcRet,lnI,1,CHR(VAL(SUBS(lcRet,lnI,1)) + 48))
    ELSE
      lcRet = STUFF(lcRet,lnI,1,CHR(VAL(SUBS(lcRet,lnI,1)) + 97))
    ENDIF
  ENDFOR
  *--- Armo código
  lcCod = lcLat + SUBS(lcRet,1,4) + lcMed + SUBS(lcRet,5,4) + lcLat
  RETURN lcCod
ENDFUNC
*------------------------------------------------------
* FUNCTION _StrToI2of5(tcString) * INTERLEAVED 2 OF 5
*------------------------------------------------------
* Convierte un string para ser impreso con
* fuente True Type "PF Interleaved 2 of 5" 
* ó "PF Interleaved 2 of 5 Wide" 
* ó "PF Interleaved 2 of 5 Text"   
* Solo caracteres numéricos
* USO: _StrToI2of5('1234567890')
* RETORNA: Caracter
*------------------------------------------------------
FUNCTION _StrToI2of5(tcString)
  LOCAL lcStart, lcStop, lcRet, lcCheck, ;
    lcCar, lnLong, lnI, lnSum, lnAux
  lcStart = CHR(40)
  lcStop = CHR(41)
  lcRet = ALLTRIM(tcString)
  *--- Genero dígito de control
  lnLong = LEN(lcRet)
  lnSum = 0
  lnCount = 1
  FOR lnI = lnLong TO 1 STEP -1
    lnSum = lnSum + VAL(SUBSTR(lcRet,lnI,1)) * ;
      IIF(MOD(lnCount,2) = 0,1,3)
    lnCount = lnCount + 1
  ENDFOR
  lnAux = MOD(lnSum,10)
  lcRet = lcRet + ALLTRIM(STR(IIF(lnAux = 0,0,10 - lnAux)))
  lnLong = LEN(lcRet)
  *--- La longitud debe ser par
  IF MOD(lnLong,2) # 0
    lcRet = '0' + lcRet
    lnLong = LEN(lcRet)
  ENDIF
  *--- Convierto los pares a caracteres
  lcCar = ''
  FOR lnI = 1 TO lnLong STEP 2
    IF VAL(SUBS(lcRet,lnI,2)) < 50
      lcCar = lcCar + CHR(VAL(SUBS(lcRet,lnI,2)) + 48)
    ELSE
      lcCar = lcCar + CHR(VAL(SUBS(lcRet,lnI,2)) + 142)
    ENDIF
  ENDFOR
  *--- Armo código
  lcRet = lcStart + lcCar + lcStop
  RETURN lcRet
ENDFUNC


Daniel Vargas.
MCP - Microsoft Certified Professional

"El callar y escuchar es cosa de sabios por ello nuestro grito nace de silencio consciente fuerte y elocuente... vivir de manera diferente es morir siendo libre"

Elkin Ramirez-Kraken

My Blog
Previous
Reply
Map
View

Click here to load this message in the networking platform