Modelo de Factura con macros para imprimir, exportar a PDF y generar resúmenes

Modelo de factura para OpenOffice LibreOffice Calc

Tras varias consultas realizadas en el Foro Oficial en español al respecto, ponemos a vuestra disposición este modelo para emitir facturas en OpenOffice Calc, que sirve también para LibreOffice Calc.

El modelo no pretende ser una solución de facturación; tan sólo es un ejemplo de cómo utilizar algunas técnicas avanzadas en la hoja de cálculo y de cómo automatizar determinadas tareas mediante el uso de macros, creadas con la grabadora de macros, y levemente adaptadas.

Por supuesto que el modelo es muy mejorable, y cada uno deberá, si pretende utilizarlo, adaptarlo a sus necesidades. Nuestra intención es ilustrar algunas de las posibilidades y dar pistas de cómo aplicarlas.

Veamos sin más las técnicas utilizadas en el mismo.

Encabezado de la factura

Logotipo y datos de la empresa

Tras insertar una imagen (Insertar > Imagen > Desde archivo...), que tras ajustarla en posición y tamaño, ha sido bloqueada enviándola al fondo de la hoja desde su menú contextual > Posición  > En el fondo. Para poder seleccionarla, consulta Seleccionar una imagen situada en el fondo de la hoja


 

Para los datos de la empresa que factura hemos utilizada Ctrl+Intro en modo edición para insertar varias líneas en la celda, y hemos aplicado diferentes propiedades a los texto siguiendo el sistema comentado en este artículo: Aplicar varios formatos al texto de una celda en Calc.


Numerador de factura

Símplemente se ha añadido desde la barra de herramientas Campos de control de formulario (podemos mostrarla desde el menú Ver > Barras de herramientas) un Botón de selección; en modo diseño de formulario (segundo botón de la barra de herramientas) editamos las propiedades del Control (tercer botón de la barra de herramientas con el control seleccionado); desde la ficha Datos lo hemos relacionado con la celda C3. Desde la ficha General hemos definido el valor máximo en 10.000.000.

 

 

Botones para lanzar macros

Desde esta misma barra de herramientas hemos añadido con su herramienta Botón los botones para lanzar las macros (octavo botón en la barra); editando sus propiedades desde la pestaña Acontecimientos, asignamos las macros creadas previamente a los botones en su evento Botón del ratón soltado.

 

 

Finalmente, desactivamos el modo diseño de formulario y cerramos la barra de herramientas.

 

Selector del cliente

Se ha utilizado la técnica Validez... del menú Datos, asociando la celda D3 con un intervalo de celdas definido en la hoja Datos. A la hora de definir el intervalo, siempre dejaremos la primera celda del rango vacía para hacer más sencilla la selección del cliente.

 

 

 

Datos del cliente

En las celdas D4,D5 y C5 hemos utilizado la función BUSCARV para que rellene los datos del cliente seleccionado en la celda D3

Hemos anidado la función BUSCARV dentro de una función SI, que detecta si D3 está vacío; en caso afirmativo, rellena las celdas con nada (""); en caso contrario, las rellena con el resultado de la búsqueda.

Suponemos que los datos del domicilio de cada cliente se escriben por completo en una única celda, utilizando Ctrl+Intro para añadir nuevas líneas dentro de la celda cuando estamos editando su contenido.

 

Líneas de detalle de la factura

Los colores de fila alternos se aplican mediante la técnica descrita en este artículo: Ponle el pijama a tus hojas de OpenOffice Calc con formato condicional.

 

 

El rango de celdas B8:B37 permiten seleccionar el código del artículo utilizando la misma técnica que hemos utilizado para el código del cliente.

 

 

Las columnas Descripción y Precio utilizan la función BUSCARV de nuevo anidadas en una función SI para evitar que muestren algo si el código del artículo está vacío.

La columna Importe incorpora una fórmula que calcula el importe neto de la línea, también anidada en una función SI con el mismo objetivo que la anterior.

 

Pié de la factura

Forma de pago y vencimientos

La celda B40 permite seleccionar la forma de pago también utilizando la técnica de validez de celdas

 

 

 

El rango de celdas B43:C46 muestran los vencimientos en función de la forma de pago seleccionada. Las formas de pago se definen en la hoja Datos, y permiten definir hasta 4 pagos en partes alícuotas, indicando el número de días a transcurrir desde la fecha de factura hasta el vencimiento.

El primer vencimiento se calcula restando del total los otros vencimientos, de forma que en caso de diferencias por redondeo, se acumulen o resten del primero.

 

Descuentos, portes e impuestos

La celda G40 permite definir un porcentaje de descuento a aplicar al total bruto.

La celda F42 permite introducir un número de envíos en concepto de portes, mientras que la celda G42 permiten introducir el coste de cada envío.

Total bruto  - Descuento + Portes conforman el total antes de impuestos

Las celdas G44 y G45 permiten seleccionar el porcentaje de IVA y de Recargo de equivalencia a aplicar al total antes de impuestos.

Dado que este es un modelo de cómo utilizar determinadas técnicas, no se ajusta a ninguna normativa en particular, por lo que si el usuario decide utilizarlo deberá adaptarlo a la normativa de su país.

 

Hoja protegida

Se ha protegido la hoja para que no se puedan siquiera seleccionar las celdas que no tienen que editarse.

 

 

Las celdas que sí pueden editarse fueron previamente desprotegidas desde Formatear celdas... > Protección de celda, como podeis leer en este capítulo de nuestra wiki: Ocultar, mostrar y proteger en Calc.

 

Celdas y rangos de celdas con nombre

Para facilitar la personalización y modificación del modelo sin tener que editar las macros, se han creado los siguientes nombres de celdas y rangos:

Celda o rango con nombre Hoja Celda o rango Importante para
CodCliente Factura D3 Varias
DatosFactura Factura K7:K28 Exportar a Resumen
DescuentoFact Factura G40 Vaciar datos
FormaPago Factura B40
ImprimirFactura Factura B1:H46 Imprimir /
Generar PDF
NumFactura Factura C3
Portes Factura F42:G42 Vaciar datos
RecargoEquiv Factura G45
ResumenInsertarFila Resumen A35 Exportar a Resumen
ResumenTotales Resumen A38
VaciaCantidad Factura E8:E37 Vaciar datos
VaciaCodigos Factura B8:B37
VaciaDtos Factura G8:G37

 

 

En caso de personalizar la factura, y tener que mover estas celdas o rangos de celdas de lugar, o cambiar el número de líneas o columnas que conforman alguno de los rangos, se deben redefinir los nombres para no tener que modificar las macros y que todo siga funcionando correctamente.

Para saber más sobre rangos y celdas con nombre, consulta Definir rangos o celdas con nombre.

 

Exportar los datos a la hoja Resumen

La macro que realiza este proceso se llama EnviarDatos, y está asociada al primer botón Enviar datos a Resumen.

Los datos que se quieren exportar a la hoja resumen han sido duplicados mediante vínculos al nombre DatosFactura (rango K7:K28) en una columna para simplificar el proceso que realiza la macro. La macro copia estos datos y mediante pegado especial, transponiendo, pegar los datos en la hora Resumen en forma de fila.

Las columnas J y K se han ocultado a propósito.

En la exportación se utiliza el nombre ResumenInsertarFila para localizar la posición donde insertar la nueva fila.

Se utiliza el nombre CodCliente para volver de nuevo a la hoja Factura tras exportar los datos a la hoja Resumen.

 

Sub EnviarDatos
'----------------------------------------------------------------------
  Dim document   As Object
  Dim dispatcher As Object

  document   = ThisComponent.CurrentController.Frame
  dispatcher = CreateUNOService("com.sun.star.frame.DispatchHelper")

  Dim aSaltarA(0) As New com.sun.star.beans.PropertyValue
  aSaltarA(0).Name = "ToPoint"
  aSaltarA(0).Value = "DatosFactura"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())

  dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())

  aSaltarA(0).Value = "ResumenInsertarFila"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())

  Dim aMover(1) As New com.sun.star.beans.PropertyValue
  aMover(0).Name = "By"
  aMover(0).Value = 1
  aMover(1).Name = "Sel"
  aMover(1).Value = False
  dispatcher.executeDispatch(document, ".uno:InsertRows", "", 0, Array())

  Dim aPegadoEspecial(5) As New com.sun.star.beans.PropertyValue
  aPegadoEspecial(0).Name = "Flags"
  aPegadoEspecial(0).Value = "SVDN"
  aPegadoEspecial(1).Name = "FormulaCommand"
  aPegadoEspecial(1).Value = 0
  aPegadoEspecial(2).Name = "SkipEmptyCells"
  aPegadoEspecial(2).Value = False
  aPegadoEspecial(3).Name = "Transpose"
  aPegadoEspecial(3).Value = True
  aPegadoEspecial(4).Name = "AsLink"
  aPegadoEspecial(4).Value = False
  aPegadoEspecial(5).Name = "MoveMode"
  aPegadoEspecial(5).Value = 4

  dispatcher.executeDispatch(document, ".uno:InsertContents", "", 0, aPegadoEspecial())

  aMover(0).Value = 22
  dispatcher.executeDispatch(document, ".uno:GoRight", "", 0, aMover())

  aMover(0).Value = 1
  dispatcher.executeDispatch(document, ".uno:GoUp", "", 0, aMover())

  aMover(1).Value = True
  dispatcher.executeDispatch(document, ".uno:GoRight", "", 0, aMover())

  dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())

  aMover(1).Value = False
  dispatcher.executeDispatch(document, ".uno:GoLeft", "", 0, aMover())
  dispatcher.executeDispatch(document, ".uno:GoDown", "", 0, aMover())

  aPegadoEspecial(0).Value = "A"
  aPegadoEspecial(3).Value = False
  dispatcher.executeDispatch(document, ".uno:InsertContents", "", 0, aPegadoEspecial())
  
  aSaltarA(0).Value = "ResumenInsertarFila"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())  

  aSaltarA(0).Value = "CodCliente"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  
  MsgBox ("Datos enviados a la hoja Resumen", 192, "open-office.es")

End Sub

 

Imprimir la factura

La macro que realiza este proceso se llama ImprimirFactura, y está asociada al primer botón Imprimir Factura.

Se utiliza el nombre ImprimirFactura para definir el área de impresión, o sea, las celdas a imprimir.

Se utiliza el nombre CodCliente para situar el cursor en esa posición tras definir el área de impresión.

La macro redefine el área de impresión y muestra el diálogo Imprimir para seleccionar la impresora de salida y otros ajustes.

Si se desea que se presente el diálogo Formato de página (disponible desde la vista preliminar para ajustar las opciones de página, encabezado, etc.) puedes descomentar la línea correspondiente en la macro.

Sub ImprimirFactura
'----------------------------------------------------------------------
  Dim document   As Object
  Dim dispatcher As Object

  document   = ThisComponent.CurrentController.Frame
  dispatcher = CreateUNOService("com.sun.star.frame.DispatchHelper")

  Dim aSaltarA(0) As New com.sun.star.beans.PropertyValue
  aSaltarA(0).Name = "ToPoint"
  aSaltarA(0).Value = "ImprimirFactura"

  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:DefinePrintArea", "", 0, Array())

  aSaltarA(0).Value = "CodCliente"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())

  ' descomentar la siguiente línea para presentar el diálogo Formato de página
  ' dispatcher.executeDispatch(document, ".uno:PageFormatDialog", "", 0, Array())
  dispatcher.executeDispatch(document, ".uno:Print", "", 0, Array())

End Sub

 

Generar PDF

La macro que realiza este proceso se llama GenerarPDF, y está asociada al primer botón Generar PDF.

Se utiliza el nombre ImprimirFactura para definir el área de impresión y el nombre CodCliente para situar el cursor en esa posición tras definirla.

Se utiliza el nombre NumFactura para componer el nombre del documento PDF generado.

 

La macro redefine el área de impresión y muestra el diálogo Exportar factura en formato PDF para seleccionar la carpeta destino y modificar, si se considera oportuno, el nombre del documento PDF generado.

Esta macro utiliza para tal fin la función GuardarComo, basada en una función similar tomada del libro de Mauricio Aprendiendo OOo / LibO Basic

Sub GenerarPDF
'----------------------------------------------------------------------
  Dim document   As Object
  Dim dispatcher As Object
  Dim numFactura As String
  Dim CarpetaNombrePDF As String

  document   = ThisComponent.CurrentController.Frame
  dispatcher = CreateUNOService("com.sun.star.frame.DispatchHelper")

  Dim aSaltarA(0) As New com.sun.star.beans.PropertyValue
  aSaltarA(0).Name = "ToPoint"
  aSaltarA(0).Value = "ImprimirFactura"

  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:DefinePrintArea", "", 0, Array())

  aSaltarA(0).Value = "CodCliente"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())

  numFactura = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("NumFactura").getString()
  CarpetaNombrePDF = GuardarComo( "Factura " & numFactura )

  If CarpetaNombrePDF > "" Then

    Dim args2(1) As New com.sun.star.beans.PropertyValue
    args2(0).Name = "URL"
    args2(0).Value = CarpetaNombrePDF
    args2(1).Name = "FilterName"
    args2(1).Value = "calc_pdf_Export"

    dispatcher.executeDispatch(document, ".uno:ExportDirectToPDF", "", 0, args2())

  EndIf

End Sub


Function GuardarComo( cNombre As String ) As String
'----------------------------------------------------------------------
  Dim oDlgGuardarArchivo As Object
  Dim mDlgOpciones()
  Dim mArchivo() As String
  Dim mOpciones()

  oDlgGuardarArchivo = CreateUNOService ("com.sun.star.ui.dialogs.FilePicker")
  mDlgOpciones = Array(com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_AUTOEXTENSION)

  With oDlgGuardarArchivo
    .Initialize ( mDlgOpciones() )
    .AppendFilter( "Documentos PDF (.pdf)", "*.pdf" )
    .Title = "Exportar factura en  formato PDF"
    .SetDefaultName(cNombre)
  End With

  If oDlgGuardarArchivo.Execute() Then
    mArchivo() = oDlgGuardarArchivo.getFiles()
    GuardarComo = mArchivo(0)
  End If

End Function

 

Vaciar datos

La macro que realiza este proceso se llama VaciarDatos, y está asociada al primer botón Vaciar datos.

Se utilizan varias nombres de celdas y de rangos para reiniciar los datos de la factura..

Tras utilizar este botón, las celdas afectadas se mostrará vacías de contenidos, incluídos los comentarios que albergaban.

Sub VaciarDatos
'----------------------------------------------------------------------
  Dim document   As Object
  Dim dispatcher As Object

  document   = ThisComponent.CurrentController.Frame
  dispatcher = CreateUNOService("com.sun.star.frame.DispatchHelper")

  Dim aSaltarA(0) As New com.sun.star.beans.PropertyValue
  aSaltarA(0).Name = "ToPoint"
  aSaltarA(0).Value = "VaciaCodigos"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "VaciaCantidad"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "VaciaDtos"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "FormaPago"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "Portes"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "DescuentoFact"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "RecargoEquiv"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

  aSaltarA(0).Value = "CodCliente"
  dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, aSaltarA())
  dispatcher.executeDispatch(document, ".uno:ClearContents", "", 0, Array())

End Sub

 

 

Hoja Factura

Desde la barra de herramientas lateral se ha desactivado la opción Mostrar líneas de cuadrícula de la celda.

 

Hoja Datos

Para que el método de selección de un dato utilizando la técnica de Validez sea más natural, es importante dejar la primera celda del rango vacía.

En las funciones BUSCARV utilizadas en la hoja Factura, las tablas de búsqueda incluyen hasta la fila 50; se ha marcado de forma especial la última fila para recordar que en caso de necesitar más líneas, deben insertarse por encima de esa marca, con el fin de que las fórmulas se actualicen automáticamente.

 

Hoja Resumen

Las dos primera y las dos últimas filas que se ven en la hoja no deben eliminarse para que todo funcione perfectamente.

Cuando se insertan nuevas filas se copia automáticamente el formato de las filas anteriores;además, las celdas de las columnas W y X contienen fórmulas que automáticamente copia la macro de la fila anterior a la insertada. Por eso no debemos eliminar ni la fila 2, ni el contenido, ni el formato de sus celdas.

Para que se actualicen automáticamente las fórmulas de las dos últimas filas (los totales) debe respetarse la fila situada justo encima, que no debe eliminarse ni ocultarse.

Se ha activado el filtro automático (autofiltro) para obtener fácilmente información del resumen.

Descargar el modelo

Si quieres descargar el modelo, haz clic sobre el siguiente enlace:

Descargar Modelo Factura Openoffice Libreoffice Calc

 

 

6 comentarios

Comentario De: Meredith [Visitante]

Hola!

Yo tengo un modelo de factura hecho en excel donde tengo protegido el documento excepto las casillas de fecha, nº de factura, Nombre cliente, Nif cliente y direccion cliente.

Tengo un modelo en una hoja y otro modelo en otra hoja dependiendo de la consulta donde yo trabaje ese dia.

Mi problema es que para exportar a PDF la hoja actual que estoy usando, calc me exporta todo el documento (todas las hojas) y yo solo quiero la que está activa (en uso), de modo que cada vez que quiero exportar una factura tengo que seleccionar todo el rango de la hoja activa del documento y exportar sólo la selección.

¿Se puede hacer una macro para exportar una hoja a pdf? ¿Como puedo hacerla?

Gracias.

30.06.15 @ 17:00
Comentario De: [Miembro]

Hola Meredith:

En cuanto a la impresión ocurre igual en Calc que en Excel. Debes configurarlo adecuadamente seleccionando un rango de impresión para que imprima la factura y no todas las hojas.

Este ejemplo incluye una macro que exporta el rango de impresión a PDF; en realidad, exporta el rango de impresión definido, pues exportar a PDF es equivalente a imprimir.

Espero que te sirva.

30.06.15 @ 23:23
Comentario De: Alberto [Visitante]  

Buenas Tardes.
Descargue el archivo y coloque mis datos (imagen, nombre de empresa....), pero a la hora de ejecutar los macros, estes no me funcionan. Nose que puede pasar, la macro que mas me interesa es la de enviar datos a resumen.
Por favor, necesito ayuda.

15.03.16 @ 17:14
Comentario De: [Miembro]

Hola Alberto
Dada la dificultad de establecer un diálogo en este blog mediante comentarios, recomiendo que te dirijas al Foro Oficial de OpenOffice y expongas allí el problema. Podremos ayudarte más rápidamente que por aquí.
Saludos

02.04.16 @ 10:37
Comentario De: oscar [Visitante]

Hola masters, tengo un problema utilice el codigo para hacer unos respaldos de datos el problema que me dio es que cuando actualice a la version nueva de openoffice 5.1 dejo de funcionar, me graba en cualquier parte menos de forma ordenada como lo estaba haciendo.

13.04.16 @ 19:31
Comentario De: oscar [Visitante]  

Hola.
primero que nada excelente aplicación, me estaba funcionando bien hasta que se me ocurrio actualizar el office con lo que estaba trabajando era la libreoffice 4.1 y funcinaba de maravilla actualize a libreoffice 5.1 y al momento de grabar los datos no los graba como corresponde. quisiera saber si hay alguna posibilidad de poder hacer funcionar en esa version esta excelente aplicación.

14.04.16 @ 23:21


Form is loading...