Translate

viernes, 28 de septiembre de 2012

Automatización de Detracciones...(En construcción)

Algunas veces nos complicamos con las detracciones.

Por ejemplo:

Errores de cálculo

[Se toman porcentajes que no corresponden]
[Se toma el tipo de cambio que no corresponde]

Errores de declaración

[Se toma un proveedor o cliente que no corresponde]

Errores de control

[Se duplica la detracción]
[No se cumple con pagar la detracción]
[Se cumple con pagar la detracción de manera extemporánea]
[No se contabiliza la detracción]
[Se contabiliza mal la detracción]
[Se duplica la contabilización de la detracción]
[Mayor costo...la detracción individual cuesta S/. 3.50 la detracción masiva cuesta S/. 10.50 por ilimitado numero de detracciones]
[Complicaciones al momento de fectuar la conciliación bancaria]

etc, etc

Como resultado tenemos multas con SUNAT, escritos a SUNAT para solicitar reimputaciones, escritos a clientes o proveedores para solicitar devoluciones, las cuentas por pagar a proveedores descontroladas, mayor esfuerzo en el análisis de cuentas, etc, etc

Ya suficiente tenemos para un problema / tarea adicional no?

A continuación y a modo de ejemplo, tratare de orientar una solución utilizando VBA de Excel enlazando CONCAR.

Como ya es mi costumbre recuerdo que también es aplicable a SAP Bussines One, SISCONT, etc




Por obvias razones he borrado los datos de la empresa que utiliza este aplicativo. (Los datos suprimidos y el logo se encontraban en los recuadros con bordes rojos)

El aplicativo encierra una serie de detalles.

Analicemos algunas:

Como es de público conocimiento, una de las obligaciones formales en el Registro de Compras consiste en anotar el número y la fecha de la constancia de detracción.

Para ello CONCAR solicita estos datos (y otros más) al momento de registrar la factura de compra.


Entonces, se deduce que para CONCAR primero se paga la detracción y luego se registra la factura. Asi como lo plantea CONCAR antes de registrar la factura se debe de pagar la detracción, o en todo caso abrir el registro y editarlo. Para pagar la detracción se tiene que digitar en la web de SUNAT y después volver a digitar en CONCAR. Dos veces el mismo registro: RUC, Proveedor, Importe, etc. Doble registro para una misma acción = Ineficiente.

En este punto yo discrepo, resulta más eficiente:

1. Registrar la compra en CONCAR
2. Obtener los datos mediante consulta SQL y volcarlos en MS Excel
3. Completar las fechas, código del bien y código de operación
4. Imprimir el cálculo

El punto 1 es manual en CONCAR los siguientes puntos son automáticos en MS Excel

Esto ayuda a contar con evidencia física del cálculo de la detracción, a contar con una base de datos histórica, a generar los archivos de texto para migrar masivamente a la web de SUNAT, a migrar el número y fecha de constancia al registro de compras, a migrar el asiento de pago a la contabilidad, etc, etc

Por otro lado, el hecho de colocar algún dato dentro de los campos de detracción origina que CONCAR realice un asiento contable agregando 2 líneas adicionales. La cuenta 42103 se denomina Anticipo por detracción y se reconoce como cuenta por pagar, la contrapartida es la cuenta de factura por pagar y se reconoce como crédito.


Finalmente, CONCAR necesita registrar el asiento de pago de la detracción:

Las transacciones de las figuras anteriores no estan relacionadas. Sólo se debe de tener en cuenta la dinámica de las cuentas. Se ha borrado el nombre de usuario y los códigos de anexo.

Volviendo al tema del excel, el aplicativo contiene un botón de comando llamado "COPIAR TABLAS", esto es necesario porque está vinculado a la versión del CodeBase del CONCAR. No seria necesario si la versión fuese SQL o si la fuente de datos externa fuera le SAP Bussines One. El motor de consulta de SQL es más potente y los datos se obtienen más rápido.

Veamos el contenido del código del botón "COPIAR TABLAS" y de paso vemos algunos conceptos de programación, los comandos Kill, On Resume Next, etc y un tema interesante FileCopy Versus CopyFile.

Private Sub cmd_Copiar_Tablas_Click()
    Pregunta_1 = MsgBox("Se recomienda copiar las tablas al inicio de cada sesión de trabajo." & vbCrLf & "Después ya no resulta necesario a menos que Ud. asi lo indique." & vbCrLf & vbCrLf & "¿Esta seguro de copiar las tablas?", vbYesNo)
    If Pregunta_1 = vbYes Then
        Application.StatusBar = "Espere...Copiando tablas desde CONCAR para evitar lentitud"
        On Error Resume Next
        Carpeta = "C:\Documents and Settings\Usuario\Escritorio\Aplicativos\TABLAS TEMPORALES"
        Kill ("" & Carpeta & "\CCC0312.DBF")
        Kill ("" & Carpeta & "\CCD0312.DBF")
        Kill ("" & Carpeta & "\CAN02.DBF")
        Dim fs As Object
        Dim oldPath As String, newPath As String
        oldPath = "W:\REAL\CONCAR80"
        newPath = "C:\Documents and Settings\QuinecheR\Escritorio\Aplicativos\TABLAS TEMPORALES"
        Set fs = CreateObject("Scripting.FileSystemObject")
        fs.CopyFile oldPath & "\" & "CCC0312.dbf", newPath & "\" & "CCC0312.dbf"
        fs.CopyFile oldPath & "\" & "CCD0312.dbf", newPath & "\" & "CCD0312.dbf"
        fs.CopyFile oldPath & "\" & "CAN02.dbf", newPath & "\" & "CAN02.dbf"
        Set fs = Nothing
        Application.StatusBar = False
    End If
End Sub


No olvidemos que las palabras que aparecen de color "azul" son las reservadas por Visual Basic. Coloco azul entre comillas porque desde el editor de Visual Basic se puede configurar el color (Herramientas / Opciones / Formato del Editor)

Cuando usted crea una macro, estas, empiezan con la palabra SUB esto es el convecionalismo para Subrutina, ¿? Asi es, una macro puede contener otra macro y asi de simple se crea un proceso dentro otro proceso, por ejemplo:

Sub Macro1()
      Macro2
End Sub

Las macros "existen" en módulos, los módulos son como hojas de word, en ellas se digitan las sentencias de programación.

En VBA de Excel:
el libro tiene un módulo
cada hoja de cálculo cuenta con su módulo
se puede insertar un módulo independiente
se puede insertar un formulario y este tambén tiene su módulo.

Cuando se inserta un control Active X dentro de una hoja de cálculo, como por ejemplo, el botón de comando "COPIAR TABLAS" el bóton pertenece a la hoja, por lo tanto la programación se encuentra dentro del módulo de la hoja.

La diferencia entre un macro y un manejador de evento es que las macros son públicas, se encuentran accesibles en todos los módulos. El manejador de evento comienza con la palabra Private Sub e indica que sólo es accesible en el módulo en que ha sido creado.

La función MsgBox muestra un cuadro de mensaje. Generalmente se utiliza asi:

Sub Macro1()
      MsgBox "Hola"
End Sub

Sin embargo, este cuadro de mensaje puede mostrar opciones para responder SI o NO, etc. De esta manera se crea interacción con el usuario y la macro sabe como actuar según la respuesta.

La sintaxis cambia, se coloca un texto como por ejemplo Pregunta_1 seguido del signo igual.

Luego la función Msgbox pero seguida de un parentesis de apertura y un paréntesis al final.

Pregunta_1 = MsgBox("Se recomienda copiar las tablas al inicio de cada sesión de trabajo." & vbCrLf & "Después ya no resulta necesario a menos que Ud. asi lo indique." & vbCrLf & vbCrLf & "¿Esta seguro de copiar las tablas?", vbYesNo)

Entre comillas va el texto que desea mostrar al usuario.

vbCrlf es una constante "retorno de carro automático" para cuando se usaba las máquinas de escribir, actualmente seria el enter en word.

vbYesNo es el argumento, los argumentos son las "partes variables" de una función, como por ejemplo: =REDONDEAR(A1,2) donde 2 es la variable que indica que el redondeo es a dos decimales, variable porque puede ser -3, -2, -1, 0, 1, 2, 3, etc.

Entre cada constante vbCrlf uso comillas dobles ("") y el ampersand (&) como concatenador.


If Pregunta_1 = vbYes Then

Si la respuesta a pregunta_1 es SI, entonces, la barra de estado de Excel muestra el siguiente mensaje: Espere...Copiando tablas desde CONCAR para evitar lentitud

Application.StatusBar = "Espere...Copiando tablas desde CONCAR para evitar lentitud"

Esto es porque la versión de CONCAR no es SQL. Se utiliza este artificio para ejecutar la consulta SQL que trataremos más adelante y obtener los datos desde CONCAR hacia Excel.

On Error Resume Next
Ignora los errores de programación o del usuario. Esto es peligroso ya que la macro podria ejecutar un accion que no deseamos como borrar datos y después no podamos recuperarlos.

Carpeta = "C:\Documents and Settings\Usuario\Escritorio\Aplicativos\TABLAS TEMPORALES"
La palabra Carpeta esta siendo usada como una variable, en este caso como no ha sido declarada la variable por defecto VBA la define como Variant. Variant acepta todo. Lo correcto hubiera sido declararla como String. Asi:

Dim Carpeta As String

Las variables se declaran antes de ser utilizadas, esto ahorra memoria. Es preferible hablar de variables luego, ya de por si, lo explicado hasta el momento, puede resultar bastante confuso, si no se lee con detenimiento.

La ruta "C:\Documents and Settings\Usuario\Escritorio\Aplicativos\TABLAS TEMPORALES" apunta hacia la carpeta TABLAS TEMPORALES ubicada en el escritorio.

Kill ("" & Carpeta & "\CCC0312.DBF")

La sentencia Kill borra / elimina un archivo.

Utilizo la variable Carpeta para no tener que digitar la ruta. De lo contrario, la sentencia hubiera sido:

Kill ("C:\Documents and Settings\Usuario\Escritorio\Aplicativos\TABLAS TEMPORALES\CCC0312.DBF")

Noten que la ruta es un texto (Va entre comilla dobles) y que para concatenarla uso nuevamente doble comillas ("") y ampersand (&).

Dim fs As Object
Dim oldPath As String, newPath As String

Aparecen 3 varibles declaradas de la siguiente manera:

fs declarada como Objecto
oldPath (Antigua carpeta) como texto (Van a referirse a la ruta de inicio)
newPath (Nueva carpeta) como texto (Van a referirse a la ruta de destino)

Tal y como menciona la ayuda de Visual Basic las variables pueden ser:

Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal, Date, String, Object, Variant

En este caso se ha declarado fs como Object, fs por las siglas de FileSystem. Pudo haber sido cualquier otro texto. Se recomienda que sea relacionado con el proceso o la acción que ejecuta.

En el mundo cotidiano definir un objeto pude ser complicado, podemos hacer referencia a una cosa material pero tambien a una cosa abstracta como por ejemplo: "En este blog la programación aplicada a la contabilidad será nuestro objeto de estudio e investigacion".

Al fin o intento al cual se le dirigira una acción lo conocemos popularmente como objeto.

En el mundo de la programación es más complicado. Sin embargo, los objetos tiene una identidad, un comportamiento y un estado.

Una identidad que los diferencian con los demás, un comportamiento que esta relacionado con sus funciones y un estado relacionado con el valor de sus atributos o propiedades (Tamaño, color, alto, ancho, etc.)

Asi un objeto puede ser "dibujado" en un formulario o dentro de una hoja de cálculo, se pude ver y medir, un objeto pude contener otros objetos, por ejemplo Excel es un objeto, dentro de Excel 2003 hay otros objetos: una barra de menú, barras de herramientas, una barra de estado, una barra de fórmula, hojas, rangos, celdas, barras de desplazamiento horizontal y vertical, etc, etc, etc...Todos ellos son objetos, se diferencian de otros objetos, tienen un comportamiento y estados (Por ejemplo: Barras ocultas o Barras visibles, donde: ocultas / visibles son los estados)

En este caso Object es para hacer referencia a un Objeto, el cual no necesariamente debe ser "dibujado", podemos hacer referencia al objeto "de forma abstracta" y con ello tener acceso a sus funciones (Métodos) y Atributos (Propiedades)

Por Ejemplo, la siguiente macro abre Word desde el Editor de Visual Basic de Excel

A diferencias de las otras variables los objetos nescesitan ser "seteados", es decir configurados/ asignados, para ello se utiliza la palabra calave Set.

Set fs = CreateObject("Scripting.FileSystemObject")
Por lo tanto, esta sentencia hace referencia la objeto FileSystem.




Para mayor conocimiento del objeto FileSystem visite http://support.microsoft.com/kb/186118/es

fs.CopyFile oldPath & "\" & "CCC0312.dbf", newPath & "\" & "CCC0312.dbf"
        fs.CopyFile oldPath & "\" & "CCD0312.dbf", newPath & "\" & "CCD0312.dbf"
        fs.CopyFile oldPath & "\" & "CAN02.dbf", newPath & "\" & "CAN02.dbf"

Ahora podemos usar el metodo CopyFile del objeto fs (Scripting.FileSystemObject) para copiar la tabla CCC0312.dbf del CONCAR (Esta tabla es la cabecera del libro diario) desde la carpeta de origen en la red hacia la nueva carpeta en el escritorio


De la misma forma, con las tablas del CONCAR CCD0312.dbf (El detalle del libro diario) y CAN02.dbf (La tabla de anexos: Proveedores, clientes, trabajadores, etc.)

La ventaja de usar CopyFile en lugar de la función FileCopy es que esta última, no permite copiar las tablas si el CONCAR esta en uso.

Para mayor conocimiento de la función FileCopy visite


No olviden la nomenclatura;

CCC0312 donde: CCC (cabecera) 03 (Número o código de empresa) y 12 (Año en formato AA)

CAN02.dbf donde: CAN (Es una sola tabla, es decir cabecera y detalle al mismo tiempo) y 02 (Número o código de empresa, en este caso la tabla de anexos de la empresa 02 sirvio para uso "público" para las distintos periodos, en su sistema talvez tenga otro número, por ejemplo CAN01.dbf o tan sólo CAN.dbf)

Set fs = Nothing

Libera la memoria, es decir se hace referencia a nada. Un objeto ocupa parte de memoria fisica, cuando esta en ejecución.

Application.StatusBar = False

Restablece la barra de estado de Excel. Con esto aparece nuevamente la palabra "Listo" en la barra de estado.

End If

Cierra la estrucura If

End Sub

Cierra la Rutina

Por fin acabo esto! Que complicado resulto explicar el funcionamiento del botón Copiar Tablas!!!

Poco código pero con bastante fundamento.

Y además, se trato varios conceptos de programación.

Ahora veamos, el código del botón Obtener Datos

De aqui en adelante los procedimientos son orientados al cálculo de la detracción.

Como el botón ha sido insertado dentro de la hoja de cálculo "CONSTANCIA" la programación se encontrará en el módulo de esta hoja.

La forma de "dibujar" un botón de comando dentro de una hoja de cálculo ya ha sido tratada en otras entradas de este mismo blog. Asicomo, también la forma de asignar sus propiedades.

Dibuje el botón OBTENER DATOS y desde la ventana de propiedades asigne la propiedad nombre a cmd_Consultar_Datos

Presione el botón derecho del mousesobre el botón y seleccione Ver Código

Copie y pegue las siguientes sentencias:

Private Sub cmd_Consultar_Datos_Click()
    If Range("G2") <> "" Then
        ActiveSheet.Unprotect Password:=123
        Set con = CreateObject("adodb.connection")
        Set rs = CreateObject("adodb.recordset")
        con.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Documents and Settings\Usuario\Escritorio\Aplicativos\TABLAS TEMPORALES;Extended Properties = dBase 5.0;"
        rs.Open "SELECT Top 1 DCODANE FROM CCD0312 WHERE DSUBDIA='" & Left(Range("G2"), 2) & "' AND DCOMPRO = '" & Right(Range("G2"), 6) & "' AND DCUENTA LIKE '42%'", con
        Range("D11").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT Top 1 DNUMDOC FROM CCD0312 WHERE DSUBDIA='" & Left(Range("G2"), 2) & "' AND DCOMPRO = '" & Right(Range("G2"), 6) & "' AND DCUENTA LIKE '42%'", con
        Range("D13").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT Top 1 DFECDOC2 FROM CCD0312 WHERE DSUBDIA='" & Left(Range("G2"), 2) & "' AND DCOMPRO = '" & Right(Range("G2"), 6) & "' AND DCUENTA LIKE '42%'", con
        Range("D15").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT Top 1 DFECCOM2 FROM CCD0312 WHERE DSUBDIA='" & Left(Range("G2"), 2) & "' AND DCOMPRO = '" & Right(Range("G2"), 6) & "' AND DCUENTA LIKE '42%'", con
        Range("D19").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT Top 1 DIMPORT FROM CCD0312 WHERE DSUBDIA='" & Left(Range("G2"), 2) & "' AND DCOMPRO = '" & Right(Range("G2"), 6) & "' AND DCUENTA LIKE '42%'", con
        Range("D23").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT Top 1 DCODMON FROM CCD0312 WHERE DSUBDIA='" & Left(Range("G2"), 2) & "' AND DCOMPRO = '" & Right(Range("G2"), 6) & "' AND DCUENTA LIKE '42%'", con
        Range("G23").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT Top 1 CTIPCAM FROM CCC0312 WHERE CSUBDIA='" & Left(Range("G2"), 2) & "' AND CCOMPRO = '" & Right(Range("G2"), 6) & "'", con
        Range("D25").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT TOP 1 ADESANE FROM CAN02 WHERE AVANEXO='P' AND ACODANE='" & Range("D11") & "'", con
        Range("G11").CopyFromRecordset rs
        rs.Close
        rs.Open "SELECT TOP 1 AREFANE FROM CAN02 WHERE AVANEXO='P' AND ACODANE='" & Range("D11") & "'", con
        Range("D33").CopyFromRecordset rs
        If Len(Range("D33")) <> 11 Then
            MsgBox "El número de cuenta " & Range("D33").Text & "es incorrecto!" & vbCrLf & vbCrLf & "Por favor verifique que la cuenta conste de 11 digitos, luego:" & vbCrLf & vbCrLf & "1. Modifique en el Concar" & vbCrLf & "2. Copie las tablas y" & vbCrLf & "3. Obtengas los datos nuevamente", vbExclamation
            Range("D33").ClearContents
        End If
        Set rs = Nothing
        Set con = Nothing
        ActiveSheet.Protect Password:=123
    Else
        MsgBox "Registre el Voucher Contable", vbInformation
    End If
End Sub

Desarrollo explicativo de las sentencias de programación:

If Range("G2") <> "" Then verifica que la celda G2 no se encuentre vacia

En la celda G2 el usuario debe de digitar el número de voucher de compras, es usual que Concar utilice el subdiario 14 para las compras
ActiveSheet.Unprotect Password:=123 desprotege la hoja de cálculo, la contraseña asignada fue 123

En este punto tenemos que recordar la protección y el bloqueo / desbloqueo de celdas

Por defecto MS Excel bloquea todas las celdas. Como las únicas celdas a las que debe de tener acceso el usuario son las de: fecha de pago, fecha de traslado, Código del bien o servicio y el código de operación, entonces solamente estan celdas deberán ser desbloqueadas.

Para desbloquer celdas, seleccionelas y desde el menú Formato/Celdas ficha Proteger desmarque la casilla de verificación Bloquear


Luego, desde el menú Herramientas/Protección/Proteger hoja asigne y confirme la contraseña, en este caso 123


Comprabará que sólo será posible seleccionar las celdas desbloqueadas.

Set con = CreateObject("adodb.connection")
Set rs = CreateObject("adodb.recordset")

Se declaran las variables de objeto, a diferencia de los otros tipos de variables los objeto se deben de declarar prededidos de Set

con es la variable, puede ser cualquier otra palabra pero conviene utilizar una palabra relacionada en este caso con es disminutivo de conexión

rs es la otra variable, en este caso rs es disminutivo de recordset



Entrada en construcción...






No hay comentarios:

Publicar un comentario en la entrada