Obtener impresora seleccionada mediante runcommand accmdprint

Tengo varios informes que quiero imprimir. Sé que puedo en un mismo evento ejecutar el mismo comando para imprimirlos a la vez, pero me gustaría que sólo se eligiera una vez la impresora, y una vez hecho, se imprimieran todos los demás a través de la misma.

1 respuesta

Respuesta
2

Llevo un buen rato (pero bueno, bueno...) navegando por aquí y por allá para encontrar una solución a tu pregunta, pero lamento comentarte que no he encontrado la manera de detectar qué impresora se ha seleccionado en el accmdprint. Ciertamente ha sido desesperante.

Si te interesa puedo darte un código para poder predeterminar, antes de imprimir, la impresora que se quiere utilizar, lo que implicaría no utilizar el accmdprint.

Ya me dirás si te interesa esa solución. Si no... pues por ahora no podría darte una respuesta utilizando el accmdprint. En fin... no se puede saber todo ;(

Lo dicho: espero tus comentarios.

Un saludo

http://neckkito.eu5.org // http://neckkito.16mb.com/Access

En principio lo que tú me comentas creo que sé cómo hacerlo, pero de todas formas, si no te importa me gustaría ver el código que me propones, pues siempre se puede aprender cosas nuevas de códigos de otras personas.

Gracuas

Si sabes cómo "pillar" la impresora que se ha seleccionado a través del cuadro de diálogo de impresoras, te ruego que me pases cómo hacerlo, porque sigo sin encontrar una solución a eso.

Te explico un poco el sistema:

Las impresoras del sistema conforman una colección, y las impresoras son los elementos de esa colección son, precisamente, las impresoras. Y cada impresora tiene un índice (ten en cuenta que los índices de las colecciones empiezan por cero, no por uno).

¿Cómo saber cuál es el índice de las impresoras de tu sistema? Pues a través de este código:

...

Sub listaImpresoras()
'Declaramos las variables
Dim miImpr As Printer
Dim i As Byte
'Recorremos la colección de impresoras, mostrando
'un MsgBox con la información sobre cada una de ellas
For Each miImpr In Application.Printers
With miImpr
MsgBox "Nombre de la impresora: " & .DeviceName & vbCrLf _
& "Índice: " & i
i = i + 1
End With
Next miImpr
End Sub

...

Supongamos que queremos ser restrictivos, y que de todas las impresoras sólo queremos que el usuario seleccione 2 (te pongo el ejemplo para 2 impresoras, pero puedes poner la cantidad que quieras). Podemos utilizar para ello un marco de opciones. Por ejemplo, queremos que sólo se pueda elegir la impresora de índice 0 y la impresora de índice 4.

Para ello te creas un marco de opciones, y configuras el asistente así:

1.- ¿En la primera ventana escribimos el nombre de las impresoras que queremos que se utilicen? Siguiente
2.- ¿Podemos establecer como opción predeterminada la que queramos? Siguiente
3.- Para la primera impresora especificamos el valor 0 (cero), puesto que sabemos que ese es su índice. Para la segunda establecemos el valor en 4, porque, evidentemente, ¿ese es su índice? Siguiente
4.- ¿Damos el formato que queramos? Siguiente
5.- ¿Cómo título podemos escribir algo como “Seleccione impresora”? Finalizar
6.- A ese marco de opciones le ponemos de nombre mrcSelImpr (Propiedades del marco -> Pestaña Otras -> Nombre)

Y ahora, por ejemplo en un botón de comando, en el evento "Al hacer click" generamos el siguiente código:

...

Private Sub ...
On Error GoTo sol_err
'Declaramos las variables
Dim indiceImpr As Long
'Obtenemos el índice del elemento seleccionado (que será el valor
'que hemos asignado en la configuración del marco de opciones)
indiceImpr = Me.mrcSelImpr.Value
'Establecemos la impresora seleccionada como la impresora
'por la que se debe imprimir
Set Application.Printer = Application.Printers(indiceImpr)
'Imprimimos los informes que queremos
DoCmd.OpenReport "Informe1"
DoCmd.OpenReport "Informe2"
'etc
Salida:
Exit Sub
sol_err:
If Err.Number = 2501 Then
MsgBox "Canceló la impresión", vbExclamation, "CANCELADO"
Else
MsgBox "Se ha producido el error: " & Err.Number & " - " & Err.Description
End If
Resume Salida
End Sub

...

Ten en cuenta que ahora la impresora predeterminada PARA ACCESS es la que acabamos de predeterminar, y hasta que no salgas de Access, por defecto, se cogerá la que ha seleccionado el usuario. Si quieres que, tras el proceso, la situación vuelva a ser la "original" tienes que añadir una nueva predeterminación de la impresora al final del código, dentro de la etiqueta Salida. Por ejemplo, si la impresora predeterminada quieres que sea la de índice 1 modificarías el código así (te escribo sólo la etiqueta Salida; el resto del código sería el mismo):

...

Salida:

Set Application.Printer = Application.Printers(1)

Exit Sub

...

Y eso es todo. A ver si esta solución es válida para tu BD.

¿Has podido probar la solución? Simplemente me ha extrañado no recibir noticias tuyas.

Hola, verás, es que hasta hoy no he ido a trabajar, y he estado bastante liada, así que no he podido probarla. Es posible que tarde unos días, es lo que pasa cuando haces varias cosas a la vez xD.

En cuanto lo pruebe te comento.

Si fueras hombre no podrías hacer más que una sola cosa a la vez... je, je... Eso tiene sus ventajas... :P

Ok. Esperaré con ansia tus comentarios.

He estado pensando una cosa. Si existe otra solución con otro comando también me sirve. Yo puse el accmdprint porque era el que mejor conocía.

Otra cosa, he estado experimentando con el acCmdQuickPrint, pensando que imprimía por la impresora seleccionada, pero cada informe me lo imprime por una impresora distinta. Es decir, uno me lo imprime por la impresora física, y los otros por la de pdf. Conoces tú este comando? Igual eso pueda servirme.

Ya me comentas algo. Muchas gracias y un saludo.

Vamos a ver si clarificamos un poco la cosa. Si digo alguna cosa que ya sepas te pido disculpas, pero piensa que "yo no sé que tú sabes" ;-) :
FASE 1
- Cuando utilizas Docmd. RunCommand estás diciendo que quieres realizar una operación de emulación de las acciones que puedes realizar a través de los elementos del menú.
- En el menú tienes dos opciones: Imprimir e Imprimir... (con puntos suspensivos)
- Cuando utilizas DoCmd. RunCommand acCmdPrint estás emulando la opción "Imprimir...", y por ello te sale el cuadro de diálogo de las impresoras
- Cuando utilizas DoCmd. RunCommand acCmdQuickPrint estás emulando la opción "Imprimir", y por ello te imprime directamente el documento.
FASE 2
- Si no tocaras nada la impresora por defecto, para Access, es la impresora por defecto del sistema.
- Si configuras el informe para que salga por una impresora la impresora por defecto para ese informe es la configurada, no la de Access (que si tampoco se ha dicho nada sigue siendo la del sistema).
- Si cambias la impresora predeterminada en Access (a través de Set Application.Printer = Application.Printers(indiceImpr), y a partir de ese momento, la impresora predeterminada para TODO Access es la que acabas de predeterminar, que no es la misma que la predeterminada del sistema. Los informes te saldrán pues por la predeterminada de Access (no del sistema, salvo que coincidan, claro) y salvo que en el propio informe hayas configurado su salida por otra impresora distinta.
- En fin... que espero que quede claro porque con una lectura rápida lo anterior puede parecer una explicación un poco "retorcida", pero es así.
FASE 3
En resumen:
- Si quieres que todos los informes te salgan por la misma impresora, y que no sea la predeterminada del sistema, tienes que:
1.- Predeterinar la impresora en Access (a través de Set Application. Printer)
2.- Confirmar que los informes no tienen otra impresora asignada (es decir, que la que tienen asignada es la opción "Impresora predeterminada")
FASE 4
Te hablo de cabeza, y no recuerdo bien los detalles, pero con las primeras versiones de Access 2007 había un "bug" que hacía que, a pesar del "rollo" que te he soltado antes, acCmdQuickPrint imprimiera por donde "le salía de ahí". En el año 2008 Microsoft sacó un "parche" para solventar eso.
Como estamos en el año 2012 y se supone que hemos ido actualizando nuestro Access no deberías tener ningún problema por este "bug".
De todas maneras insisto en que lo anterior te lo digo "sacado de mis recuerdos", pero creo que es interesante saberlo.
FASE 5
Despedida y cierre... Je, je...
Eso es todo por ahora. Si tienes alguna duda me comentas.

Vale, me ha quedado bastante clara toda tu explicación, pero me queda una duda. Has dicho que los informes tienen una opción llamada impresora predeterminada? porque yo no la veo, y puede que sea ese mi problema.

Como no es una opción que utilice habitualmente ahora no recuerdo el detalle de dónde está la opción, y "en mis manos" sólo tengo 2003 ahora.

En Access 2003 sitúas el informe en vista preliminar -> Configurar página -> Pestaña página, y ahí te encuentras un "apartado" que te indica "Impresora para nombreInforme", con dos opciones:

- Impresora predeterminada

- Usar impresora especificada (junto a un botón que te permite elegir la impresora que quieras).

A ver si con esto puedes echar un vistazo a tu BD y e indagar por ahí si encuentras la opción.

Si no me lo comentas y, si llego a una hora prudencial a casa (que hoy en teoría llego tarde), lo miro en mi Access. Si no te lo tendré que mirar mañana.

De momento me he apañado poniendo en cada informe a imprimir report1.printer=report2.printer. No es la mejor opción pero n tengo otra. Lo que me da miedo es poner una impresora en concreto a saco, pues cuando cambien la impresora o estén en otro sitio no funcionará.

Lo ideal sería poder hacer report1.printer=runcommand accmdprint, pero bueno, ya sabemos que eso no se puede.

Pues ya no sé qué más decirte. Como te comentaba al principio de esta larguísima consulta ;-) no he podido encontrar ningún código que me "capte" qué opción elige el usuario.

Si como lo has hecho te funciona bien, pues perfecto.

No será porque no lo he intentado... Y lamento no haberte podido dar una solución mejor. Desgraciadamente... "no sé más".

Voy a comentarte la mejor solución que he encontrado.

Para empezar he creado un formulario nuevo llamado Impresoras con un marco de opciones, siete en mi caso porque no creo que puedan haber muchas más, con todas ellas no visibles.

En el evento Load del formulario he creado el código para ir rellenando las opciones con los nombres de las distintas impresoras que se detecten:

Private Sub Form_Load()
Dim <span class="scayt-misspell" data-scaytid="40" data-scayt_word="i">i</span>
Dim imrpn As Printer
i = 1
For Each ImprN In Application.Printers
rellenar i, ImprN.DeviceName
i = i + 1
Next
End Sub

La función de ayuda es la siguiente:

Function rellenar(i, Impresora)
If i = 1 Then
Opcion1.Visible = True
Me.Etiqueta1.Caption = Impresora
Opcion1.OptionValue = i - 1
End If
If i = 2 Then
Opcion2.Visible = True
Me.Etiqueta2.Caption = Impresora
Opcion2.OptionValue = i - 1
End If
If i = 3 Then
Opcion3.Visible = True
Me.Etiqueta3.Caption = Impresora
Opcion3.OptionValue = i - 1
End If
If i = 4 Then
Opcion4.Visible = True
Me.Etiqueta4.Caption = Impresora
Opcion4.OptionValue = i - 1
End If
If i = 5 Then
Opcion5.Visible = True
Me.Etiqueta5.Caption = Impresora
Opcion5.OptionValue = i - 1
End If
If i = 6 Then
Opcion6.Visible = True
Me.Etiqueta6.Caption = Impresora
Opcion6.OptionValue = i - 1
End If
If i = 7 Then
Opcion7.Visible = True
Me.Etiqueta7.Caption = Impresora
Opcion7.OptionValue = i - 1
End If
End Function

Éste mismo formulario tiene un botón, llamado Aceptar, que recoge la información rellenada por el usuario, en este caso, la impresora seleccionada. Una vez leída se pasa al informe principal que se quiere imprimir y desde el que se imprimen todos los demás. Éste es el código:

Private Sub btAceptar_Click()
Debug.Print "Se ha seleccionado la impresora: " & Impresoras
DoCmd.OpenReport "InformeTeardown", acViewReport
Report_InformeTearDown.Impresora = Impresoras
DoCmd.Close acForm, "Impresoras"
Report_InformeTearDown.impresion
End Sub

Una vez rellenada la información, la función del informe a la que se llama es la que se encarga de imprimir todos los informes a través de esa misma impresora. Éste es su código:

Function impresión()
Dim i
Dim ImprActiva As String
Dim ImprN As Printer
Set Me.Printer = Application.Printers(Impresora.Value)
Debug.Print Me.Printer.DeviceName
DoCmd.RunCommand acCmdQuickPrint
If btDefectos.Enabled = True Then
DoCmd.OpenReport "Defectos", acViewReport 'Defectos
Report_Defectos.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Defectos"
End If
DoCmd.OpenReport "Comentarios", acViewReport 'Comentarios
Report_Comentarios.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
'DoCmd.RunCommand acCmdSelectReport
DoCmd.Close acReport, "Comentarios"
DoCmd.OpenReport "ParesTeardown2", acViewReport 'Pares de apriete
Report_ParesTearDown2.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "ParesTeardown2"
If Me.btRelComp.Enabled = True Then
DoCmd.OpenReport "RelCompr", acViewReport 'Relación de compresión
Report_RelComp.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "RelCompr"
End If
If Me.btSegmentos.Enabled = True Then
DoCmd.OpenReport "Segmentos", acViewReport 'Segmentos
Report_Segmentos.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Segmentos"
End If
If Me.btBloque.Enabled = True Then
DoCmd.OpenReport "Bloque", acViewReport 'Bloque
Report_Bloque.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Bloque"
End If
If Me.btPistones.Enabled = True Then
DoCmd.OpenReport "Pistones", acViewReport 'Pistones
Report_Pistones.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Pistones"
End If
If Me.btlevas.Enabled = True Then
DoCmd.OpenReport "ArboldeLevas", acViewReport 'Arbol de levas
Report_ArboldeLevas.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "ArboldeLevas"
End If
If Me.btBielas.Enabled = True Then
DoCmd.OpenReport "Bielas", acViewReport 'Bielas
Report_Bielas.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Bielas"
End If
If Me.btCiguenyal.Enabled = True Then
DoCmd.OpenReport "Ciguenyal", acViewReport 'Cigueñal
Report_Ciguenyal.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Ciguenyal"
End If
If Me.btTaque.Enabled = True Then
DoCmd.OpenReport "Taques", acViewReport 'Taqués
Report_Taques.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Taques"
End If
If Me.btValvulas.Enabled = True Then
DoCmd.OpenReport "Valvulas", acViewReport 'Válvulas
Report_Valvulas.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Valvulas"
End If
If Me.btMuelles.Enabled = True Then
DoCmd.OpenReport "Muelles", acViewReport 'Muelles
Report_Muelles.Printer = Me.Printer
DoCmd.RunCommand acCmdQuickPrint
DoCmd.Close acReport, "Muelles"
End If
End Function

Aunque considero que no es necesario, diré, por si acaso, que todo este empieza con un evento asociado a un botón del informe principal que abre el formulario de las impresoras tal que así:

Private Sub btImprimirTODO_Click()
DoCmd.OpenForm "Impresoras"
End Sub

Supongo que no es la mejor solución, pero yo creo que es aceptable. Espero que te guste y, aunque tú sabes más que yo, que puedas aprender algo más. Muchas gracias por todo.

He echado un vistazo a tu código y, además del "currazo" que veo que te has pegado, hay un par de ideas de "sistemática" que me han gustado. Digamos que... "tomo nota" :D

Creo que deberíamos cambiar los papeles, y debería ser yo quien cerrara la consulta y te puntuara ;-)

Te agradezco muchísimo que hayas compartido tu código y que te hayas "esforzado" (por decirlo de alguna manera) en buscar soluciones. Así aprendemos todos, creo yo.

Finalmente, todavía no conozco un "medidor de conocimientos" fiable. Por eso te agradezco el "piropo implícito" que me echas, pero, como te comentaba, cada día aprendo cosas nuevas gracias a gente como tú.

Para lo que necesites ya sabes.

Un gran saludo,

Neckkito

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas