API impresión

Hay una nueva versión en Android de la API de impresión, con más características, más flexible y más eficiente, cuyo módulo es independiente del framework, aunque siga invocándose desde el script.

Es preferible usarla frente a ésta, que será marcada obsoleta.

http://www.xoneisp.com/xonewiki/doku.php?id=b.-programacion:b18.-extras:b18.4.-nueva-api-impresion:start

IMPRESIÓN

El control de impresión con XOne está implementado de forma que las órdenes se impriman directamente, mediante funciones SCRIPT, optimizando el uso de memoria que habitualmente consume este tipo de controles.

  • La impresión está disponible en todas las plataformas excepto IPHONE.
  • En Windows Mobile, el archivo printer.xml también tiene que estar pasado a .bin.
  • En Windows Mobile, si NO se va a utilizar el fichero listdirect(antiguo método de impresión), es aconsejable no incluirlo en la instalación, de lo contrario, tendríamos un consumo de memoria innecesario.
  • El método de impresión directo mediante SCRIPT está disponible también con el listdirect.
  • En Android, no es necesario pasarle parámetros a startprint, pues la impresora se selecciona desde un menú.
  • Recordar que cada impresora podría tener sus propios comandos de inicialización y los que sirven para una pueden no valer para otra.
  • Las impresoras Bluetooth suelen usar el lenguaje de programación CPCL para comunicarse.
  • En caso de no funcionar correctamente, comprobar si el modelo lo tenemos homologado y consultar la documentación de la impresora para ver los comandos de inicialización y tal.

Módulo impresión en Android

Para Android, es necesario instalar el .apk del servidor de impresoras. Para usarlo, antes de mandar algún documento a imprimir, se debe activar el bluetooth y sincronizar con la impresora.

Una vez hecho esto, mandar a imprimir el documento siguiendo el procedimiento descrito abajo, y tras invocar startprint, debería salir el menú de selección de impresora. Pulsar la tecla menú en el dispositivo y seleccionar scan.

Se han implementado las siguientes funciones para controlar la impresión desde script sin necesidad de usar el fichero de plantillas listdirect.bin (antiguo método de impresión).

Conecta con la impresora que se indique por parámetro y queda preparada para imprimir.
Si la conexión es correcta devuelve 0, en caso contrario, un código de error.

Versión del comando anterior específica para Android. Debemos especificar qué driver de impresión usar, si no, usará un driver genérico. Si no se especifica stPrinterType, cargará el driver de la impresora Datecs.

Valores posibles: brother, zebra, datecs.

Ejemplo de uso:

    ui.StartPrint "zebra"

En el caso de seleccionar el driver de la brother, podemos concatenar “$$” seguido del modelo de impresora. Si no se especifica, cargará el modelo PJ-662.

Ejemplo de uso:

    ui.StartPrint "brother$$PJ-562"

Imprime la cadena que recibe por parámetro.
Si la impresión es correcta devuelve 0, en caso contrario un código de error.

Imprime la cadena que recibe por parámetro y realiza un salto de línea.
Si la impresión es correcta devuelve 0, en caso contrario un código de error.


Imprime comandos específicos de la impresora, mediante la cadena que recibe por parámetro.
Si la impresión es correcta devuelve 0, en caso contrario un código de error.

  • Para escribir texto normal y que el control los interprete como ASCII, sería:
COMANDO SALIDA
appdata.userinterface.printcommand “##TEXT##hola 130 15 ##END_TEXT## “hola 130 15 “
appdata.userinterface.printcommand “##TEXT##! 0 200 200 210 1##END_TEXT## ”! 0 200 200 210 1”
  • Cualquier valor que vaya entre comas sin las macros anteriores, será interpretado como un valor ASCII:
COMANDO SALIDA
appdata.userinterface.printcommand “32,35,104,111,108,97,10 ” #hola” (el codigo ascii 10 es un linefeed)
appdata.userinterface.printcommand “32,35,##TEXT##hola##END_TEXT##,10 ” #hola” (este comando es idéntico al anterior)

Sólo disponible usando el driver de impresión brother.

Imprime el archivo PDF especificado en el primer parámetro. Si solamente se especifica el nombre del fichero, lo buscará en la carpeta files de la aplicación.


Sólo disponible usando los driver de impresión zebra, brother, datecs. Si el nombre del fichero acaba en _TEMP, lo borrará al imprimir.
Imprime una imagen.

Primer argumento Ruta en la cual buscará el fichero imagen a imprimir. Acepta ficheros .gif, .png, .jpg, y .bmp. Puede ser una URL.
Segundo argumento Especifica el ancho de la imagen a imprimir. Si éste o el tercer argumentos son igual a cero, no se reescalará la imagen.
Tercer argumento Especifica el alto de la imagen a imprimir. Si éste o el segundo argumentos son igual a cero, no se reescalará la imagen.
Cuarto argumento Alineación.
Quinto argumento No implementado. Poner 0 en su lugar.


Ejemplo: ui.printimage “logo.png”, “100”, “100”, “center”, “0”

Realiza tantos saltos de línea como se indiquen por parámetro.
No retorna nada.


Sólo Android y sólo implementado en el driver de la Brother, por características de esta. Configura si al terminar de imprimir, saca todo el papel hasta el final de la página o se queda ahí.

Valores posibles endofpage, free, endofpageretract, fixedmode.


Sólo Android. Imprime un código de barras o QRCode.

Códigos de barras soportados codabar, code11, code128, code25, code39, code93, datamatrix, ean128, ean13, ean8, isbn, issn, itf14, identcode, interleaved2of5, leitcode, msi, onecode, pdf417, planet, postnet, rm4scc, upca, upce.


Ejemplo de uso:

ui.PrintBarcode "ean128", "(00)350123451234567894" , "ancho", "alto"

Para QRCode:

ui.PrintBarcode "qrcode", "BIZCARD:N:Pepito;X:Grillo;T:Programador informático;C:CGSoft;A:Dirección;B:+34921212121;F:+34924242424;M:+34902002255;E:email@servidor.com;;" , "ancho", "alto"


Finaliza la conexión a la impresora y destruye el objeto.

En Android, espera unos 15-20 segundos aproximadamente a que la impresora termine antes de dar timeout.

Retorna:
-2 si el tiempo de espera ha pasado
-1 si ha habido algún error
0 si todo ha ido correcto


En ocasiones nos topamos con impresoras más lentas o en las que hay que cargar cada hoja manualmente, como la Brother PJ-662, y hay que darle más tiempo de espera. Para ello, podemos pasarle como argumento un entero que indica en segundos el tiempo de espera.
Si se le especifica -1 como argumento, esperará de manera infinita a que termine o ocurra un error.


(ejemplo antiguo)
Para poder imprimir, primero es necesario llamar a la función startprint, indicando como parámetro cual de las entradas del fichero printer.bin vamos a usar.

StartPrint 0 –> Usaría la 1ª entrada del fichero printer.bin
StartPrint 1 –> Usaría la 2ª entrada del fichero printer.bin


y finalizar con endprint.

result = appdata.userinterface.StartPrint( numimpre )
 
If result = 0 Then
    appdata.userinterface.PrintCommand "27,45,48"
    appdata.userinterface.PrintCommand "27,53"
    appdata.userinterface.PrintLine "HOLA..."
    appdata.userinterface.Print "ADIOSSS...."
    appdata.userinterface.LineFeed 4
    appdata.userinterface.EndPrint
End If

Este ejemplo se ha probado en Android con la impresora Zebra MZ 220. Tened en cuenta la limitación de 30 caracteres por línea.

'err = appdata.userinterface.MsgBox("Texto", "Mensaje", 1)
'El tope máximo es de 30 caracteres por línea o pasarán cosas raras
'Usar cstr
'Añadir +chr(13)+chr(10) al final de cada PrintLine
'imprimirLiquidacion() da el tiket entero
'imprimirFormateado() imprime dos cadenas, la segunda alineada a la derecha
'imprimirFormateadoDetalle() hace el formato especial para tres cadenas
'By Reaper

function imprimirInformeBonificaciones()
	Dim nreg, filtro
	coddelegacion = appdata.getCollection("Delegaciones")("ID",user("IDDELEGACION"))("CODIGO")
	
	appdata.userinterface.StartPrint "zebra"
	imprimirNormal("******************************")
	imprimirNormal("*     *    INFORME     *     *")
	imprimirNormal("*     * BONIFICACIONES *     *")
	imprimirNormal("******************************")
	imprimirFormateado "DELEGACION: "+cstr(coddelegacion), cstr(day(Now()))+"/"+cstr(month(Now()))+"/"+cstr(year(Now()))
	imprimirNormal("OPERADOR: "+user("CODIGOTRABAJADOR"))
	imprimirNormal(user("NOMBRETRABAJADOR"))
	imprimirNormal("  "+chr(13)+chr(10)+"  ")
	imprimirNormal("CLIENTE")
	imprimirNormal("TIPO CONCEPTO          IMPORTE")
	imprimirNormal("---- --------          -------")
	
	cambio=1
	total=0
	
	'Imprimir bonificaciones
	Set objBonificaciones = appdata.getCollection("BonificacionesListadoImprimir")
	objBonificaciones.startBrowse
	while not objBonificaciones.currentItem is nothing
		set objCLI=objBonificaciones.currentItem
		a=objCLI("MAP_CLIENTE")
		if cambio=1 then
			imprimirNormal("  ")
			imprimirNormal(objBonificaciones.currentItem("MAP_CLIENTE") + "  " + objBonificaciones.currentItem("MAP_CLIENTE1"))
			imprimirNormal("  ")
		end if
		aux = objBonificaciones.currentItem("MAP_IMPORTE")
		imprimirFormateadoInformeBonificaciones objBonificaciones.currentItem("MAP_CODIGOBONIFICACION"), objBonificaciones.currentItem("MAP_BONIFICACION1"), aux
		total = total + aux
		objBonificaciones.moveNext
		if not objBonificaciones.currentItem is nothing then
			if cstr(a)<>cstr(objBonificaciones.currentItem("MAP_CLIENTE")) then
				cambio=1
			else 
				cambio=0
			end if
		end if
	wend
	objBonificaciones.endBrowse
	set objBonificaciones = nothing
	'Fin bonificaciones

	imprimirNormal("                       -------")
	imprimirNormal("  ")
	imprimirFormateado "Total bonificaciones:", total
	imprimirNormal("  "+chr(13)+chr(10)+"  "+chr(13)+chr(10)+"  "+chr(13)+chr(10)+"  ")
	appdata.userinterface.EndPrint
end function

function imprimirNormal(txtimpr01)
	txtimpr01 = cstr(txtimpr01)
	while (len(txtimpr01) > 30)
		aux = Mid(txtimpr01, 31, len(txtimpr01))
		txtimpr01 = Mid(txtimpr01, 1, 30)
		appdata.userinterface.PrintLine(txtimpr01+chr(13)+chr(10))
		txtimpr01 = aux
	wend
	appdata.userinterface.PrintLine(txtimpr01+chr(13)+chr(10))
end function

function imprimirFormateado(txtimpr01, txtimpr02)
	txtimpr01 = cstr(txtimpr01)
	txtimpr02 = cstr(txtimpr02)
	txtimpr03 = txtimpr01+txtimpr02
	if(len(txtimpr03) < 30) then
		diferencia = 29 - len(txtimpr03)
		for i=0 to diferencia
			txtimpr01 = txtimpr01+" "
		next
		txtimpr03 = txtimpr01+txtimpr02
	end if
	imprimirNormal(txtimpr03)
end function

function imprimirFormateadoDetalle(txtimpr02, txtimpr03, txtimpr04)
	txtimpr01 = "EUR "
	txtimpr02 = cstr(txtimpr02)
	txtimpr03 = cstr(txtimpr03)
	txtimpr04 = cstr(txtimpr04)
	if(len(txtimpr02) < 5) then
		diferencia = 4 - len(txtimpr02)
		for i=0 to diferencia
			txtimpr01 = txtimpr01+" "
		next
	end if
	txtimpr01 = txtimpr01+txtimpr02+" "
	if(len(txtimpr03) < 5) then
		diferencia = 5 - len(txtimpr03)
		for i=0 to diferencia
			txtimpr01 = txtimpr01+" "
		next
	end if
	txtimpr01 = txtimpr01+txtimpr03+" "+txtimpr04
	imprimirNormal(txtimpr01)
end function


Nótese que esta impresora no está homologada aún, y que la documentación indica que se requiere añadir un retorno de carro [chr(13)] y un salto de línea [chr(10)] a cada comando, y por ello creamos la función imprimirNormal, que también divide el texto en varias líneas si supera el límite de caracteres.

Hemos imprimido retornos y saltos de línea al principio y al final para más velocidad de impresión y para que dé espacio para poder arrancar el ticket sin cargárnoslo.

La función imprimirFormateado sirve para alinear a la derecha la segunda cadena a imprimir.
En cambio, imprimirFormateadoDetalle es específico para un proyecto anterior, pero el código es reutilizable para imprimir otro content que tenga varios campos.