lunes, 24 de diciembre de 2012

Cursos Excel y Macros online (elearning) por Excelforo. Nueva edición 2013.

En primer lugar desearos a todos una Felices Fiestas y los mejores deseos para el próximo año 2013; que lo que llegue nos haga más felices!!!.

También anunciaros que comienza una nueva edición de Cursos de Excel y Macros en modalidad elearning (online) para el nuevo año 2013, donde podrás disfrutar y aprender de los cursos Excel que te ofrezco:

Curso Excel Financiero

(ver más)

Curso Tablas dinámicas en Excel

(ver más)

Curso Excel Avanzado para versiones 2007/2010

(ver más)

Curso Macros Iniciación

(ver más)

Curso Macros Medio

(ver más)

Curso preparación MOS Excel 2010 (Examen 77-882)

(ver más)


Esta nueva edición de Cursos de Excel y macros en modalidad elearning (online) dará comienzo el próximo día 1 de enero de 2013.
Con la confianza de siempre....Anímate!!


Informarte sin compromiso en cursos@excelforo.com o directamente en www.excelforo.com.

Recuerda que ahora también imparto clases particulares de Excel en Madrid te interesa?

viernes, 21 de diciembre de 2012

VBA: Controlar el acceso a un libro de Excel.

Hace unos días me llegó una curiosa solicitud, y me pareció interesante publicarla. La cuestión planteada fué:
...como puedo hacer para dotarle a los archivos excel de un codigo invariable que me permita relacionar un archivo especifico con un alumno especifico. El problema que quiero subsanar es que los alumnos se pasan los archivos le cambian el nombre y entregan...

El asunto parece claro, de qué manera poder controlar que el libro de trabajo de un alumno no pasa de mano en mano, simplemente cambiando el nombre del fichero o cambiando algo del aspecto de formato de la hoja.
Se me ocurrió incluir un evento WorkBook_Open sencillo que verificará el acceso al libro mediante una clave de identidad, y que una vez introducida por primera vez, las posteriores exigiera siempre esta misma, y en caso contrario el libro de trabajo se cerrara.

Para ello he empleado algo recientemente explicado en este blog, la propiedad de las hojas Visible: SheetVeryHidden, que permite ocultar una hoja de cálculo de ojos indiscretos (el de los alumnos).

El primer paso es sencillo, ya que prepararemos la celda A2 de la hoja que he llamado 'DatosCheck', para que reciba y controle el primer y siguientes accesos, que será además la que ocultaremos:

VBA: Controlar el acceso a un libro de Excel.


Dentro del Explorador de proyectos del Editor de VBA, buscamos ThisWorkBook e introducimos en él el siguiente código con el evento Open:

Private Sub Workbook_Open()
Dim identificacion As String
'forzamos la realización de una pregunta de verificación
identificacion = InputBox("Identificación", "Núm identidad")
'comprobamos que la celda A2 elegida está vacía
'lo que significaría que es la primera vez que se accede al libro
If Sheets("DatosCheck").Range("A2").Value = vbEmpty Then
    'si está vacía, entonces la rellenamos con el código introducido
    'y salimos del procedimiento
    Sheets("DatosCheck").Range("A2").Value = identificacion
    Exit Sub
    Else
    'en caso contrario, verificamos que el código es el mismo introducido
    'la primera vez, si fuera diferente, cerramos el libro sin guardar cambios.
    If Sheets("DatosCheck").Range("A2").Value <> identificacion Then
    MsgBox "No corresponde!!!"
    ActiveWorkbook.Close SaveChanges:=False
    End If
End If
End Sub



Nuestro trabajo de seguridad terminará, una vez oculta (VeryHidden) nuestra hoja 'DatosCheck', protegiendo nuestro proyecto (ver cómo).

El funcionamiento es bien sencillo, al abrir el libro, aparecerá un cuadro que pedirá tu número de indetidad personal, la primera vez que se abra admitirá cualquier valor, que automáticamente quedará registrado en una hoja oculta, y el alumno podrá seguir trabajando sin problemas sobre el ejercicio propuesto.
En posteriores accesos al libro, se solicitará igualemente el número de indentidad, sólo se permitirá trabajar sobre el libro si el código introducido corresponde con el primero grabado, en caso contrario el libro se cerrará.

miércoles, 19 de diciembre de 2012

VBA: Una función personalizada para mostrar el Número de página en una celda.


Hace bastante tiempo mostré cómo conseguir identificar el número de página impresa directamente en una celda de nuestra Hoja de cálculo; mediante funciones macro 4.0 de Excel conseguíamos identificar en una celda la numeración de la hoja correspondiente al área de impresión (ver).

Hoy veremos otra forma de obtener el mismo resultado, de una manera algo más sencilla, mediante una función personalizada en VBA.


La idea sigue siendo la misma, para una hoja con un área de impresión definida, con diferentes saltos de página insertados, mostrar en la misma hoja de cálculo, en las celdas correspondientes, cuál es el número de página de un total de ellas.
Partiremos de una hoja con diferentes saltos de página:

VBA: Una función personalizada para mostrar el Número de página en una celda.



Insertamos el siguiente código VBA de nuestro procedimiento Function en un módulo del Explorador de proyectos del Editor de VBA:

Function InfoPag()
Dim iPags As Integer, iPag As Integer
Dim iCols As Integer, iCol As Integer
Dim lfilas As Long, lfila As Long
Dim x As Long, y As Long

Application.Volatile
Dim direccion As Range
'controlamos la dirección de la celda donde se encuentra la función
Set direccion = Range(Application.Caller.Address)

'contamos saltos de página (horizontales y verticales)
With ActiveSheet
    lfilas = .HPageBreaks.Count
    iCols = .VPageBreaks.Count
End With
'calculamos el número total de páginas
iPags = (lfilas + 1) * (iCols + 1)

With ActiveSheet
    'recorremos columnas hasta que encontramos entre qué saltos verticales está.
    y = direccion.Column
    x = 0
    Do
        x = x + 1
    Loop Until x = iCols Or y < .VPageBreaks(x).Location.Column
    iCol = x
    If y >= .VPageBreaks(x).Location.Column Then
        iCol = iCol + 1
    End If
    
    'recorremos columnas hasta que encontramos entre qué saltos horizontales está.
    y = direccion.Row
    x = 0
    Do
        x = x + 1
    Loop Until x = lfilas Or y < .HPageBreaks(x).Location.Row
    lfila = x
    If y >= .HPageBreaks(x).Location.Row Then
        lfila = lfila + 1
    End If
    
    'Dirigimos y calculamos el número de pagina, según este la configuración de pagína
    'bien Hacia abajo y luego hacia la derecha
    'bien Hacia la derecha y luego abajo
    If .PageSetup.Order = xlDownThenOver Then
        iPag = (iCol - 1) * (lfilas + 1) + lfila
    Else
        iPag = (lfila - 1) * (iCols + 1) + iCol
    End If
End With
'devolvemos el valor a la hoja de cálculo
InfoPag = iPag & " de " & iPags
Set direccion = Nothing
End Function



El resultado es el esperado, obtenemos en nuestras celdas la numeración de página respecto del total de páginas dentro del área de impresión.
Ojo, la función está definida bajo el supuesto que existe al menos un salto vertical y uno horizontal!!!. En caso contrario devolvería un error.
Para controlar esta situación habría que condicionar el código para el caso que .HPageBreaks.Count y .VPageBreaks.Count fueran cero...

lunes, 17 de diciembre de 2012

VBA: Optimizar el doble loop FOR...NEXT.

Es de todos conocidos que muchas veces, aunque no queramos, no nos queda más remedio que emplear la instrucción FOR...NEXT para recorrer o 'barrer' listados o rangos de nuestras hojas de cálculo; y peor aún cuando tenemos que anidar un bucle dentro de otro, aparecen nuestras peores pesadillas: los dobles bucles (doble loop). Es aquí cuando nuestros procedimientos se ralentizan hasta términos insopechados, incluso llegando al bloqueo de nuestro equipo.
Lo que se busca con estos dobles bucles es verificar alguna condición anidada. Por ejemplo, en el ejercicio que planteo, trabajamos sobre un listado de 1.000 elementos, valores repetidos entre 1 y 50. Pretendemos obtener un primer listado de esos valores repetidos (en este caso es muy simple, son valores del 1 al 50), para luego recorrer nuevamente el listado de 1.000 elementos buscando coincidencias o cualquier otra cosa.

Es lógico, por tanto, que intentemos optimizar, en la medida de lo posible estas acciones dobles. La idea es lograr limitar el segundo recorrido únicamente a las celdas de nuestro listado a estudio, limitando por tanto el tiempo destinado a ese 'barrido' de datos.
En un doble bucle sin restricciones, lo que ocurre realmente es que recorremos todos y cada uno de los elementos del listado una y otra vez, siguiendo las indicaciones.

Vamos a ver a continuación dos procedimientos similares, un primer con un doble bucle al uso, mediante el cual recorremos una y otra vez la totalidad de los elementos, tantas veces como registros únicos hallamos contado.
Mientras que en el segundo procedimiento, restringiremos el recorrido únicamente por los elementos coincidentes (que son los que nos interesan), para lo cual emplearemos la función de VBA FIND.


Insertamos el siguiente código VBA en un módulo del Explorador de proyectos VBA para el doble bucle largo:

Sub LoopTotal()
Dim celda As Object, ID As Object
Dim i As Integer
Dim mirng As String

inicio = Timer
Set unicos = New Collection
'loop en todas las celdas y agregarlas a la coleccion
For Each celda In Sheets("Pfr").Range("IDE")
    On Error Resume Next
    unicos.Add celda.Value, CStr(celda.Value)
    On Error GoTo 0
Next celda

Application.ScreenUpdating = False
'escribir los datos en la Hoja de cálculo
For i = 1 To unicos.Count
    'con un loop general (requiere mucho tiempo...)
    For Each ID In Sheets("Pfr").Range("IDE")
        'incrementamos el contador de operaciones realizadas
        x = x + 1
        'acción de búsqueda e identificación (en este ejemplo no hace nada).
        If ID.Value = unicos(i) Then
        mirng = ID.Offset(0, 2).Address
        End If
    Next ID
Next i
Application.ScreenUpdating = True

Final = Timer
Sheets("Pfr").Range("D2").Value = Final - inicio
Sheets("Pfr").Range("D3").Value = x
End Sub



Insertamos el siguiente código VBA en un módulo del Explorador de proyectos VBA para el doble bucle restringido y más óptimo:

Sub LoopControlado()
Dim celda As Object
Dim i As Integer

inicio = Timer
Set unicos = New Collection
'loop en todas las celdas y agregarlas a la coleccion
For Each celda In Sheets("Pfr").Range("IDE")
    On Error Resume Next
    unicos.Add celda.Value, CStr(celda.Value)
    On Error GoTo 0
Next celda

Application.ScreenUpdating = False
'escribir los datos en la Hoja de cálculo
For i = 1 To unicos.Count
    'con un loop controlado sobre un rango más reducido
    Dim iLoop As Integer
    Dim j As Integer
    
    'definimos variables, para iniciar la búsqeuda FIND
    Set rNa = Sheets("Pfr").Range("A2")
    'y contamos los elementos coincidentes para el valor buscado
    iLoop = WorksheetFunction.CountIf(Sheets("Pfr").Columns(1), CStr(unicos(i)))
    'iniciamos la búsqueda restringida únicamente a los valores coincidentes
    For j = 1 To iLoop
        'acción de búsqueda e identificación (en este ejemplo no hace nada).
        Set rNa = Sheets("Pfr").Columns(1).Find(What:=CStr(unicos(i)), After:=Sheets("Pfr").Range(rNa.Address), _
         LookIn:=xlValues, LookAt:=xlWhole, _
         SearchOrder:=xlByRows, SearchDirection:=xlNext, _
         MatchCase:=True)
        'incrementamos el contador de operaciones realizadas
        x = x + 1
    Next j
Next i

Application.ScreenUpdating = True
Final = Timer
Sheets("Pfr").Range("E2").Value = Final - inicio
Sheets("Pfr").Range("E3").Value = x
End Sub



La diferencia fundamental entre uno y otro radica en que el segundo Loop, en el caso óptimo recorre únicamente los valores repetidos, miestras que en el caso Total, pasa por todos los registros una y otra vez.

Vemos en la imagen el listado de 1.000 elementos repetidos (de 1 a 50), y cómo hemos asociado cada procedimiento a un Botón. En las celdas D2:E3 mediante los procedimientos reflejaremos los tiempos empleados así como el número de operaciones realizadas:

VBA: Optimizar el doble loop FOR...NEXT.


Podemos observar el ahorro de tiempo y sobre todo operaciones realizadas de uno frente a otro procedimiento... y esto es sólo para mil registros, imaginemos si trabajaramos sobre 10.000.

jueves, 13 de diciembre de 2012

VBA: Algoritmo de ordenación tipo Burbuja en Excel.

Aprenderemos hoy un truco de ordenación de datos empleando una macro de Excel. En concreto replicaremos el Método Burbuja de ordenamiento. Podemos leer algo más al respecto en nuestra amiga Wikipedia.
Vamos a replicar es este método por el cual se revisan cada elemento de una lista de valores que va a ser ordenada con el siguiente, intercambiándolos de posición si están en el orden equivocado (de mayor a meno o menor a mayor.
Lo que haremos será trabajar con los valores, asociándolos previamente a un Array, para luego replicar esa ordenación.

Para visualizar mucho mejor el funcionamiento de nuestra macro, comenzaremos viendo los datos a ordenar, vinculados a un gráfico de columnas:

VBA: Algoritmo de ordenación tipo Burbuja en Excel.



Insertamos el siguiente código VBA en un módulo del Explorador de proyectos VBA:

Option Base 1
Sub burbuja()
Dim NumEltos As Integer
Dim auxiliar As Integer
'definimos una Array de elementos a ordenar
Dim rng() As Integer
'Calculamos el número de elementos a ordenar
NumEltos = Range("B2:B22").Count

'Redefinimos la Array y la rellenamos de valores del rango B2:B22
ReDim rng(NumEltos) As Integer
For i = 1 To NumEltos
    rng(i) = Sheets("Grafico").Cells(i + 1, 2).Value
Next i

y = 0
Do
'Método de Burbuja (siguiendo algoritmo de ordenamiento)
For i = NumEltos To 1 Step -1
    For j = i To NumEltos
        'ordenamos de mayor a menor
        If rng(i) < rng(j) Then
        auxiliar = rng(i)
        rng(i) = rng(j)
        rng(j) = auxiliar
        End If
    Next j
Next i

'mostramos el resultado de la primera ordenación
'recorriendo el rango B2:B22
For x = 2 To NumEltos + 1
Sheets("Grafico").Cells(x, 2) = rng(x - 1)
Next x
'Actualizamos pantalla para mostrar resultado en el gráfico
Application.ScreenUpdating = True
y = y + 1
'la repetimos tantas veces como elementos tengamos a ordenar en el rango
Loop Until y = NumEltos
End Sub

Podemos ver en la siguiente animación el funcionamiento de la macro:

VBA: Algoritmo de ordenación tipo Burbuja en Excel.

lunes, 10 de diciembre de 2012

Localizar Referencias circulares en Excel.

Meses atrás explique en una entrada del blog (ver) una forma de trabajar con las referencias circulares mediante un método de cálculo iterativo.
En esta ocasión el asunto es más sencillo, se trata de aprender a localizar las referencias circulares con el fin de corregirlas y conseguir que los cálculos realizados en nuestras hojas de cálculo funciones correctamente (ojo con este punto, por que es frecuente que al trabajar con referencias circulares en nuestras hojas, los cálculos mostrados sean erróneos!!).

Partiremos de una sencilla tabla con algunas referencias circulares en ella:

Localizar Referencias circulares en Excel.



Tenemos como celdas con referencias circulares, esto es, celdas que se incluyen así mismas como parte de su propio cálculo, las correspondientes a la fila 6 de Impuestos (se calcula a partir del Resultado, que a su vez requiere determinar la suma de todos los gastos, incluido los 'Impuestos', lo que cierra el circulo, y hace nacer la Referencia circular), y también las celdas de la fila 7, donde el sumatorio del Total de gastos se incluye a sí mismo como parte del sumatorio.

Recordar, antes de seguir, que cuando una Referencia circular surge, Excel muestra un mensaje de advertencia:



La cuestión a explicar en esta entrada es cómo localizar esas referencias circulares. La respuesta es sencilla, tenemos una manera muy rápida en caso de que la hoja de trabajo activa sea la que contiene esas referencias circulares, dirigiendo nuestra mirada a la Barra de estado (esa barra olvidada en la parte inferior de nuestra hoja de cálculo). Lo vemos en la imagen siguiente:

viernes, 7 de diciembre de 2012

Ocultar Mostrar hojas y la propiedad VeryHidden de Excel.

Hoy hablaré de cómo poder Mostrar u Ocultar nuestras hojas dentro de un libro de trabajo, y de esa propiedad poco conocida que permite 'esconder' más profundamente una hoja de cálculo: la propiedad Visible: xlSheetVeryHidden.

El ocultar nuestras hojas está motivado por la necesidad de proteger información a ojos 'indiscretos', o simplemente simplificar el número de hojas visibles en el libro, mostrando únicamente las hojas con información relevante o final.


Para aquellos casos en los que ocultamos hojas para proteger información importante, podría ser suficiente realizar el proceso de Ocultar hojas. Lo que haremos desde la ficha Inicio > grupo Celdas > botón Formato > desplegable Visibilidad > Ocultar y mostrar.

Ocultar Mostrar hojas y la propiedad VeryHidden de Excel.


Vemos el proceso:

Ocultar Mostrar hojas y la propiedad VeryHidden de Excel.


La ventaja/desventaja de este procedimiento es la facilidad, precisamente, de mostrar u ocultar las hojas.

Para otros casos de extrema vigilancia o seguridad disponemos de la propiedad Visible: xlSheetVeryHidden, que bien desde la ficha Programador > grupo controles > botón Propiedades o bien desde el Editor de VBA podremos configurar.
Veamos una y otra manera.

La primera es con la hoja a ocultar activa, navegar hasta la ficha Programador > grupo controles > botón Propiedades, y dentro de esa ventana diálogo de Propiedades buscaremos la propiedad Visible, dentro de la cual seleccionamos: xlSheetVeryHidden.

Ocultar Mostrar hojas y la propiedad VeryHidden de Excel.


Esta acción automáticamente oculta la hoja, pero de tal forma que no aparecerá en el listado si intentaramos Mostrar hojas:

miércoles, 5 de diciembre de 2012

VBA: Maneras de acelerar nuestras macros de Excel.

Muchas veces nos hemos encontrado programando nuestras macros en Excel, y después de un tiempo incluyendo líneas y líneas de código, al ejecutarla, observamos como el tiempo de ejecución es extremadamente elevado, o muy lento (en ocasiones, incluso bloqueamos la aplicación).
En esta entrada contaré alguna de las buenas prácticas que agilizan y optimizan los tiempos de ejecución de nuestras macros... aunque a veces, ni yo mismo utilizo ;-)

Mis 15 consejos, no necesariamente por orden de importancia, serían:

1. Usar la propiedad .ScreenUpdating al inicio y final de nuestra macro, para evitar la actualización de la pantalla cada vez que se realiza una acción sobre la hoja de cálculo:

Application.ScreenUpdating=False
'... nuestro código VBA...
Application.ScreenUpdating=True



2. Emplear la propiedad .Calculation para evitar el recálculo de las operaciones de nuestra hoja:

Application.Calculation=xlCalculationManual
'... nuestro código VBA...
Application.Calculation=xlCalculationAutomatic
'o bien antes de cerrar el libro
Application.CalculateBeforeSave=True



3. Cuando sea posible usar la instrucción WITH...END WITH:

With MyLabel
    .Height = 2000
    .Width = 2000
    .Caption = "Esta es mi etiqueta"
End With



4. Liberar memoria cuando definamos variables con objeto:

Dim wsHoja as Worksheet
'Definimos la variable objeto
Set wsHoja = Hoja1
'... nuestro código VBA...
'Liberamos la memoria
Set wsHoja = Nothing



5. Este no siempre es posible, pero cuando lo sea, mejor no emplear la instrucción IF... THEN...ELSE. Por ejemplo, en lugar de:

Dim booSiNo As Boolean
Dim x As Long
If x = 13 Then
booSiNo = True
Else
booSiNo = False
End If
MsgBox booSiNo

podríamos usar:

Dim booSiNo As Boolean
Dim x As Long
booSiNo = (x = 13)
MsgBox booSiNo



6. Hacer uso de las funciones estándar de Excel en VBA en lugar de contruir procesos que hagan lo mismo. Por ejemplo utilizar el siguiente código:

MiSuma=Application.WorksheetFunction.Sum(Range("B2:C10"))

en lugar de:

For Each celda In Range("B2:C10")
MiSuma = MiSuma + celda.Value
Next celda



7. Especificar/concretar lo máximo posible a la hora de definir variables, evitando las variables tipo Variant o Object. Por ejemplo:

>Dim MiHoja As Worksheet
'mucho mejor que...
Dim MiHoja As Object 
''''''
Dim filas As Long
'mucho mejor que...
Dim filas As Variant



8. No seleccionar un rango para trabajar sobre él, si no es estrictamente necesario:

Range("C13").Font.Bold = True
'mucho mejor que...
Range("C13").Select
Selection.Font.Bold=True



9. Evitar Copiar y Pegar (Copy and Paste), empleando otras instrucciones similares, pero algo más eficientes. Por ejemplo, es mejor usar:

Range("A1:A13").Copy Destination:=Range("B1")
'O si únicamente necesitamos los valores:
Range("B1:B13").Value= Range("A1:A13").Value



10. Emplear los índices para los elementos de las colecciones, en lugar de los nombres que definen estos elementos. Por ejemplo:

Worksheets("Hoja3") 
'mejor usar
Worksheets(3)

Ojo, por que por contra, estos índices pueden cambiar, lo que generaría problemas de identificación futuros...no hay nada perfecto, verdad?.


11. Otro caso muy frecuente, el uso de "" en lugar de la variable vbNullString, mucho más efectiva.
Mejor usar

If Range("A1").Value = vbNullString Then
'...
Else
'...
End If

en lugar de

If Range("A1").Value = "" Then
'...
Else
'...
End If



12. Otra forma muy útil cuando trabajamos con eventos sobre nuestras hojas o libros (o controles), desactivar los Events al inicio de nuestra programación y activarlos de nuevo al final:

Application.EnableEvents = False
'... nuestro código VBA...
Application.EnableEvents = True



13. Intentar reducir el número de líneas de código, empleando para ello la posibilidad de escribir en una misma línea usando el separador ':' (dos puntos). Por ejemplo:

With Selection
.WrapText = True: .ShrinkToFit = False
End With
'más rápido que...
With Selection
.WrapText = True
.ShrinkToFit = False
End With



14. Declarar las variables OLE directamente. Un ejemplo:

Dim xls As Excel.Application
'mejor que...
Dim xls As Object
Set xls = CreateObject("Excel.Application")



15. Y uno más, el último pero no el menos importante (quizá sea el más utilizado). Cuando se haga necesario emplear bucles del tipo FOR, es más óptimo emplear FOR EACH...NEXT que FOR...NEXT cuando recorremos colecciones 'indexadas'. Por ejemplo, es más rápido el primero que el segundo:

Dim wsHoja as Worksheet
For Each wsHoja In Worksheets
    MsgBox wsHoja.Name
Next wsHoja
'más rápido que el siguiente..
Dim i as Integer
For i = 1 To Worksheets.Count
    MsgBox Worksheets(i).Name
Next i



Por supuesto existen otras acciones que mejoran la eficiencia de nuestras macros, pero en algún punto hay que parar, y es que la optimización del VBA no tiene fin...

lunes, 3 de diciembre de 2012

VBA: Cómo cambiar las propiedades de un documento de Excel.

Tiempo atrás comenté en este blog la manera de listar las propiedades de un documento de Excel, era una forma sencilla de visualizar estas propiedades (ver).

En esta ocasión aprenderemos una manera, igualmente sencilla, de modificar estas propiedades de un documento de Excel desde valores contenidos en celdas de nuestra hoja de cálculo.

Para ello, insertamos el siguiente código VBA en un módulo del Explorador de proyectos VBA:

Function CambioDocProp(DocProp As String, NuevoVal As String) As Boolean
Application.Volatile
On Error GoTo SalirProceso
ActiveWorkbook.BuiltinDocumentProperties.Item(DocProp) = NuevoVal
'verificamos el éxito del cambio
CambioDocProp = True
Exit Function

SalirProceso:
CambioDocProp = False
End Function



El listado completo de las propiedades de un documento de Excel sería el siguiente (ojo por que estas propiedades se definen en inglés!!!):
Title, Subject, Author, Keywords, Comments, Template, Last author, Revision number, Application name, Last print date, Creation date, Last save time, Total editing time, Number of pages, Number of words, Number of characters, Security, Category, Format, Manager, Company, Number of bytes, Number of lines, Number of paragraphs, Number of slides, Number of notes, Number of hidden Slides, Number of multimedia clips, Hyperlink base, Number of characters (with spaces), Content type, Content status, Language, Document version.


Esta función tal cual exige que al completar los dos argumentos DocProp:= propiedad a cambiar y NuevoVal:= nuevo valor de la propiedad, o bien se refieran a una celda o bien se escriban entre comillas:
=CambioDocProp("Comments";"Cambiamos los comentarios")

El resultado de la función devuelve un VERDADERO si el cambio se ha producido o un FALSO si algo falla.

Podemos ver cómo actúa realmente esta función sobre cambios en algunas propiedades. Para ello sacaremos la venta de propiedades (Panel de documentos) a la hoja de cálculo (Menú Archivo > Información > Propiedades > Mostrar Panel de documento):

VBA: Cómo cambiar las propiedades de un documento de Excel.


A continuación escribimos algunas funciones CambioDocProp que actue sobre alguna de las propiedades, viéndo como inmediatamente modifica éstas:

VBA: Cómo cambiar las propiedades de un documento de Excel.

martes, 27 de noviembre de 2012

Cursos Excel y Macros - Excelforo - Última edición 2012.

Comienza la última edición de Cursos de Excel y Macros en modalidad elearning (online) para el 2012, donde podrás disfrutar y aprender de un nuevo curso que te ofrezco:

Curso Excel Financiero (Nuevo!!!)

(ver más)

Curso Tablas dinámicas en Excel

(ver más)

Curso Excel Avanzado para versiones 2007/2010

(ver más)

Curso Macros Iniciación

(ver más)

Curso Macros Medio

(ver más)

Curso preparación MOS Excel 2010 (Examen 77-882)

(ver más)


Esta nueva edición de Cursos de Excel y macros en modalidad elearning (online) dará comienzo el próximo día 1 de diciembre de 2012.
Con la confianza de siempre....Anímate!!


Informarte sin compromiso en cursos@excelforo.com o directamente en www.excelforo.com.

Recuerda que ahora también imparto clases particulares de Excel en Madrid (te interesa?

lunes, 26 de noviembre de 2012

VBA: Barra de progreso con formulario.

Hoy toca un ejercicio con formularios (UserForm) y un poco de código VBA para conseguir que se muestre una barra de progreso proporcional al avance en la ejecución de una procedimiento.
El procedimiento consistirá en una sencilla macro que introduce hasta 24 valores correlativamente en la columna B de la hoja 1, y según avanza se muestra una barra de progreso porcentual.

Lo primero que haremos será construir nuestro formulario (UserForm) que será el que mostrará el avance porcentual del procedimiento.
Para ello insertamos un UserForm (que llamaremos 'FrmProg'), en el cual incluiremos lo siguiente. Tres etiquetas (labels) y un botón (CommandButton):
Etiq2 con Caption 'Numeración' (es una etiqueta literal, sin más)
EtiquetaProg con Caption 'Avance%' (es una etiqueta literal, sin más)
EtqAncho será la que modificaremos mediante programación para ir cambiándole la propiedad Width (Ancho) y represente el grado de avance
CmdCerrar botón (CommandButton) con Caption 'Cancelar proceso' que servirá para cancelar y detener el proceso.


Veamos la imagen del formulario, con la etiqueta 'EtqAncho' seleccionada, y su ventana Propiedades activa:

VBA: Barra de progreso con formulario.


Importante de esta etiqueta 'EtqAncho' son las propiedades de inicio:
Width = 0
BackColor = &H000000FF& (color rojo... para que resalte, podemos poner el color que queramos).


Asignamos funcionalidad al formulario, para ello haciendo doble clic en el CommandButton 'Cancelar proceso' e insertamos el código siguiente asociado a un evento Click :

Private Sub CmdCerrar_Click()
    'damos valor 1 a la variable pública definida
    CancelIt = 1
End Sub



Continuamos insertamos el siguiente código VBA en un módulo del Explorador de proyectos VBA:

Public CancelIt As Integer
Sub BarraAvance()
    'activamos la Hoja1
    'y limpiamos la columna B
    Sheet1.Activate
    Sheet1.Range("B:B").ClearContents
    Sheet1.Range("B1").Value = "Numeración..."
    'Damos valor a una constante que servirá para Salir del formulario y Proceso
    CancelIt = 0
    'Cuando un UserForm es modal, parámetro 0
    'el usuario debe responder antes mediante cualquier otra parte de la aplicación.
    'El código no subsiguiente se ejecuta hasta que se oculta o descarga el UserForm.
    'Aunque en la aplicación otros formularios estén deshabilitados cuando se muestra un UserForm,
    'otras aplicaciones no lo están.
    FrmProg.Show 0
    'Aseguramos que las etiquetas en el formulario (futurass barras) comienzan con un texto vacío...
    FrmProg.EtiquetaProg.Caption = ""
    'y un ancho de barra 0 para el grado de avance
    FrmProg.EtqAncho.Width = 0
    'El método Repaint es útil si el contenido o la apariencia de un objeto cambia de forma significativa
    'y no quieres esperar hasta que el sistema vuelva a dibujar el área automáticamente.
    FrmProg.Repaint
    'elijo el valor 24 que son +/- las filas visibles en pantalla
    totalfilas = 24
    
    For i = 1 To totalfilas
        'Recorremos el totalfilas asignando un valor
        Sheet1.Range("B1").Offset(i, 0).Value = i
        'Definimos el ancho de la barra de avance
        'en función al ancho de la etiqueta del formulario = 342
        AnchoNuevo = (i * (342 - 4)) / totalfilas
        'Asociamos los nuevos valores al formulario
        FrmProg.EtiquetaProg.Caption = "Grado avance: " & Format(i, "0,0") & " / " & _
        Format(totalfilas, "0,0") & " (" & Format(i / totalfilas * 100, "0.00") & "%)"
        FrmProg.EtqAncho.Width = AnchoNuevo
        FrmProg.Etiq2.Caption = "Número: " & i
        FrmProg.Repaint
        
        For j = 1 To 5000
            'Cede el control de la ejecución al sistema operativo, para que éste pueda procesar otros eventos
            'La función DoEvents devuelve un tipo Integer que representa el número de formularios abiertos
            'por una versión independiente de Visual Basic.
            'DoEvents devuelve 0 en el resto de las aplicaciones.
            DoEvents
            If CancelIt = 1 Then GoTo Cancelado
        Next j
    Next
    
    GoTo Salida
Cancelado:
    MsgBox "Proceso cancelado por el usuario..."
    Sheet1.Range("B1").Offset(i + 1, 0).Value = "Cancelado."
Salida:
    Unload FrmProg
End Sub


Con este código conseguimos, por un lado ir insertando en la hoja (en la columna B) una serie de valores de 1 hasta 24, condicionado mediante un Msgbox a una cancelación anticipada (mediante el CommandButton 'Cancelar proceso').
Por otro lado modificamos la etiqueta de nuestro formulario 'EtqAncho' en cuanto a su propiedad Caption y su propiedad Width, que dará el efecto de avance.

Podemos asociar nuestra macro 'BarraAvance' a un botón en la hoja de cálculo, y ejecutarla. Veríamos lo siguiente:

VBA: Barra de progreso con formulario.


Como se puede apreciar, según el procedimiento 'BarraAvance' actúa, el ancho-Width de la etiqueta se actualiza, aí como el texto-Caption que aparece.

jueves, 22 de noviembre de 2012

VBA: Gráfico de dispersión con etiquetas personalizadas.

Construiremos hoy un gráfico de dispersión sobre dos series de datos (Renta per capita y Consumo energético) sobre una lista de paises, con la peculiaridad de que, mediante una sencilla macro, agregaremos a cada punto del gráfico la etiqueta del nombre del país correspondiente. En respuesta a la cuestión planteada por un lector:
...realizar un grafico en el que se correlacione la evolución del consumo de energía (eje de ordenadas Y) con la evolución de la renta per cápita (eje de abscisas X), añadiendo las etiquetas de cada País en el punto correspondiente...

Empezaremos viendo los datos de que partimos (datos aleatorios, no reales!):

VBA: Gráfico de dispersión con etiquetas personalizadas.


El primer paso es construir el gráfico de dispersión (gráfico XY) sobre los rangos D2:D12 y G2:G12:

martes, 20 de noviembre de 2012

Gráfico a partir de datos de diferentes hojas de Excel.

Hoy daré respuesta a una cuestión planteada, con bastante frecuencia: Cómo construir un gráfico a partir de origenes de datos en diferentes hojas de cálculo.
Para poder realizar esta operación necesitaremos emplear una herramienta bastante olvidada por las versiones Excel 2007/2010: las Tablas dinámicas con rangos de consolidación múltiples (leer más).


Recordando qué es lo que conseguimos con esta Tabla dinámica 'especial' entenderemos el sentido final; y es que lo que hacemos realmente es consolidar los diferentes orígenes de datos en un único informe, a partir del cual construiremos nuestro gráfico.
Si bien, lógicamente estamos limitados por las características especiales de este tipo de tabla dinámica, diferente a la de una tabla 'dinámica normal' (basicamente la lista de campos surgen a partir de los diferentes origenes de datos y no de los rótulos/columnas de datos - recomendado leer un poco más).


Veamos el proceso completo para el siguiente ejemplo con datos en tres hojas diferentes:

Gráfico a partir de datos de diferentes hojas de Excel.


Vemos tres origenes de datos con elementos comunes para campos iguales. Nos interesa obtener un gráfico comparativo para los tres años y mostrando los valores del campo 'Importe' para los diferentes códigos.

Entonces, lo primero que haremos será construir nuestro informe de tabla dinámica con rangos de consolidación múltiple. Como estamos trabajando con Excel 2007/2010, llamaremos al Asistente de tablas dinámicas 2003, presionando Alt+t+b en la hoja de nuestro libro 'Gráfico', que será donde vamos a incorporar el gráfico:

Gráfico a partir de datos de diferentes hojas de Excel.


Aprovechamos y marcamos el informe con gráfico dinámico, además de por supuesto la opción de Rangos de consolidación múltiples.
Saltamos hasta el Paso 2b de 3 del Asistente, en el que iremos agregando los diferentes origenes de datos (de diferentes hojas):

lunes, 19 de noviembre de 2012

Curso Excel financiero - Excelforo.

Nueva oferta de Cursos de Excel y Macros en modalidad elearning (online), donde podrás disfrutar y aprender de un nuevo curso que te ofrezco:

Curso Excel Financiero (Nuevo!!!)

(ver más)


Por supuesto podrás seguir formándote con los demás cursos que imparto...

Curso Tablas dinámicas en Excel

(ver más)

Curso Excel Avanzado para versiones 2007/2010

(ver más)

Curso Macros Iniciación

(ver más)

Curso Macros Medio

(ver más)

Curso preparación MOS Excel 2010 (Examen 77-882)

(ver más)


Esta nueva edición de Cursos de Excel y macros en modalidad elearning (online) dará comienzo el próximo día 1 de diciembre de 2012.
Con la confianza de siempre....Anímate!!


El programa del nuevo curso Escel financiero es el siguiente, pero puedes informarte sin compromiso en cursos@excelforo.com o directamente en www.excelforo.com:

TEMA 1 - INTRODUCCIÓN EXCEL FINANCIERO
1. Introducción.
2. Funciones lógicas.
3. Ejemplos funciones lógicas.
4. Funciones de suma y conteo.
5. Ejemplos funciones de suma y conteo.
6. Funciones de búsqueda.
7. Ejemplos funciones de búsqueda.
8. Funciones de base de datos.
9. Ejemplos funciones de base de datos.
TEMA 2 - TRATAMIENTO DE DATOS
1. Introducción.
2. Nombres definidos.
2.1. Formas de crear un nombre.
2.2. Ejemplo de nombre definido.
3. Formatos condicionales.
4. Buscar objetivo.
5. Tablas o listas.
5.1. Ejemplo de tablas.
6. Filtros.
7. Tablas dinámicas aplicadas.
8. Texto en columnas.
9. Importar datos.
TEMA 3 - FUNCIONES FINANCIERAS I
1. Introducción.
1.1. Tabla funciones financieras.
2. Préstamo.
2.1. Ejercicio préstamo - 1.
2.2. Ejercicio préstamo - 2.
2.3. Ejercicio préstamo - 3.
3. Amortización de bienes o rentas.
4. Bonos.
4.1. Cálculo de días de vigencia de un cupón de un bono amortizable.
4.2. Cálculo de fechas de vencimiento de cupones.
4.3. Cálculo de la cantidad de cupones pendientes.
4.4. Funciones referidas a la rentabilidad del bono.
TEMA 4 - FUNCIONES FINANCIERAS II
1. Introducción.
2. Inversiones financieras.
2.1. Ejercicio 1.
2.2. Ejercicio 2.
2.3. Ejercicio 3.
3. Conversiones.
4. Letras de tesorería.
TEMA 5 - 30 EJERCICIOS PRÁCTICOS.

domingo, 18 de noviembre de 2012

Clases particulares Excel en Madrid - Excelforo.

Si vives en Madrid, y estás interesado en aprender Excel, ahora ofrezco Clases particulares (uno a uno) de Excel para todos los niveles y versiones de Excel.
Puedes informarte y leer más en Clases particulares de Excel en Madrid por Excelforo.


Por supuesto, puedes optar por la oferta de Cursos de Excel y Macros en modalidad elearning (online):

Curso Excel Financiero (Nuevo!!!)

(ver más)

Curso Tablas dinámicas en Excel

(ver más)

Curso Excel Avanzado para versiones 2007/2010

(ver más)

Curso Macros Iniciación

(ver más)

Curso Macros Medio

(ver más)

Curso preparación MOS Excel 2010 (Examen 77-882)

(ver más)


Con la confianza de siempre....Anímate!!

jueves, 15 de noviembre de 2012

Comprobación de partidas cuadradas en Excel.

Sabemos de las bondades de las funciones matriciales en Excel, y de las altas posibilidades que nos otorgan si tenemos los suficientes recursos para configurarlas.
En varias entradas anteriores del blog he explicado las dos grandes maneras de trabajar con las matriciales, a saber: Trabajar sobre rangos y obtener un único resultado, y Obtener un rango de resultados.


En el ejercicio de hoy optaremos por la primera opción, esto es, trabajaremos sobre rangos obteniendo un único resultado en una sola celda.
El objetivo de hoy es determinar de un conjunto de registros cuáles están cuadrados y cuales no, basándonos en una condición. En particular disponemos de un listado de movimientos contables de clientes, en los que se detalla registro a registro lo facturado y lo cobrado, todo ello representado (para simplificar) en tres columnas: 'Cliente' 'Debe' y 'Haber'.
Para los no iniciados en conceptos contables, los apuntes en el 'Debe' representan las cantidades facturadas y los apuntes en el 'Haber' los importes cobrados. Lógicamente todo lo facturado deberá coincidir con lo cobrado ( y viceversa).

Vemos la tabla de registros desordenados en un principio y que, posteriormente ordenaremos por 'Cliente' para visualizar mejor el concepto a conseguir:

Comprobación de partidas cuadradas en Excel.



Para comprobar si todo importe facturado por un cliente tiene su correspondiente importe cobrado (o viceversa), lo primero que haremos será convertir en una Tabla nuestro listado de trabajo. Para ello seleccionamos el rango A1:C30 y desde la ficha Insertar > Tablas > Tabla, o bien presionamos Ctrl+t.
Convertir el rango de datos en Tabla es únicamente para facilitar la posterior incorporación de nuestra fórmula matricial para cada registro de la tabla, ya que, recuerdo, la fórmula matricial trabaja sobre rangos y devuelve el resultado en una sóla celda.

Con la Tabla creada incorporaremos una nueva columna que llamaremos 'Check', donde incluiremos la fórmula matricial que nos dirá si ese registro tiene su contrapartida o no:

Comprobación de partidas cuadradas en Excel.



Y llegamos por fin a la matricial buscada que introducimos en la celda D2:
=SI(SUMA(VALOR(([Cliente]=A2)*[Haber]))=SUMA(VALOR(([Cliente]=A2)*[Debe]));"ok";"Descuadre")
ojo con la notación especial de las Tablas!!. No olvidemos validarla presionando Ctrl+Mayusc+Enter. Al hacerlo, y ser la celda D2 parte de la columna de una tabla, se autorrellenará para cada elemento (este era el motivo de convertir en Tabla el rango).

martes, 13 de noviembre de 2012

Pegar imagen vinculada en Excel 2010.

Hoy aprenderemos una herramienta curiosa, Pegar imagen vinculada, trabajando sobre Excel 2010 (válido igualmente para Excel 2007).
La utilidad que le vamos a dar a esta herramienta nos permitirá seleccionar, a nuestra discrección, ciertos gráficos situados en diferentes hojas de nuestro libro de trabajo.
Podríamos decir que vamos a construir un sistema de gráficos a la carta.


Necesitamos poca cosa, tan sólo unos gráficos construidos en hojas diferentes, para mi ejemplo, hojas llamadas 'grafico1', 'grafico2' y 'grafico3', cada uno de ellos representa los valores de una variable (no importa qué ni donde estén colocados estos gráficos).
Muy importante, asignar un nombre definido a los rangos donde se sitúen estos gráficos:
Empleados =grafico2!$D$1:$J$18
Facturación =grafico3!$D$1:$J$18
Ventas =grafico1!$D$1:$J$18
En mi ejemplo, los tres gráficos (uno por hoja) están en el mismo rango:


El siguiente paso es sencillo, seleccionamos el rango de celdas situado justo debajo de alguno de los gráficos, por ejemplo el de la hoja 'grafico1', y copiamos (presionando Ctrl+c por ejemplo. No es necesario ningún copiado especial.). Con el rango copiado, nos vamos a la hoja 'Final' donde deseamos tener el 'gráfico intercambiable' y desplegamos el botón de Pegar > Imagen vinculada:

Pegar imagen vinculada en Excel 2010.


Atención, por que lo que acabamos de pegar es una IMAGEN!!, no es un gráfico... aunque tiene la característica de estar vinculado a lo que exista en el rango copiado.
Esta es la clave de nuestro trabajo; ya que al existir un vínculo, podremos configurarlo según nos interese.

Asi que añadimos en nuestra hoja 'Final' en la celda B1 una validación de datos con una lista de nombres; en mi caso, nombres/valores que identifican cada uno de mis tres tipos de gráfico: 'Ventas; Empleados; Facturación'. Que desde luego, no es casualidad, coinciden con los nombres definidos anteriormente:
Empleados =grafico2!$D$1:$J$18
Facturación =grafico3!$D$1:$J$18
Ventas =grafico1!$D$1:$J$18

Penúltimo paso. Generamos un último nombre definido:
Analizar =INDIRECTO(Final!$B$1)
De esta forma, podremos hacer entender a Excel qué gráfico queremos visualizar.


Último paso, nuestra imagen vinculada está asociada a un rango, podemos verlo en la Barra de fórmulas al seleccionar la imagen:

viernes, 9 de noviembre de 2012

Una matricial de Excel para listar coincidencias.

Hace bastante tiempo expliqué la forma matricial de conseguir un listado de valores únicos (ver). En esta ocasión realizaremos un ejercicio similar, donde a partir de un tabla de datos, listaremos los elementos coincidentes a un criterio dado.
Veamos nuestra tabla de datos:


Nuestro objetivo es conseguir listar únicamente los valores de la columna B que coincidan con el critrerio de la columna A dado, en el ejemplo, que sea igual a N:


La fórmula matricial de Excel buscada es:
=SI.ERROR(INDICE(SI($A$1:$A$14="N";$B$1:$B$14;"");K.ESIMO.MENOR(SI(SI($A$1:$A$14="N";$B$1:$B$14;"")="";CONTARA($A$1:$A$14)+FILAS($A$1:$A$14);FILA());FILA()));"")
Recordemos, al ser matricial, se debe ejecutar presionando Ctrl+Mayu+Enter; en este caso sobre el rango seleccionado D1:D14.


Expliquemos las partes de esta fórmula. Lo primero es excluir aquellos elementos que no necesitamos, es decir, los diferentes a N. Esto lo conseguimos con la fórmula:
SI($A$1:$A$14="N";$B$1:$B$14;"")
que nos devolvería un rango, una matriz de valores, sólo con los nombres de la columna B correspondientes a un texto igual a N en la columna A:

miércoles, 7 de noviembre de 2012

Fórmula para localizar un punto de un rango de Excel.

Veamos hoy la aplicación de una fórmula de Excel empleada para localizar una condición determinada sobre rango de celdas.
Se trata de dar respuesta a una lectora del blog que planteaba la siguiente cuestión:

...Trabajo con plantas, asi que tengo una hoja excel donde en una fila tengo: dia 1 dia 2 dia 3 dia 4 asi hasta 30 dias..... y abajo el numero de germinaciones de cada dia, me gustaria añadir una columna en la que me indicara en qué dia se produce la primera germinacion, por ejemplo:

dia 1 2 3 4 5 6.........30
semillas germinan 0 0 0 2 2 4..........0

Lo que me gustaria es que en la columna me apareciera el dia 4 para saber cuantos dias tarda en germinar....

Se trata pués de descubrir una norma o patrón que sirva para identificar la posición en el rango dado que coincida con el primer valor diferente a cero con el que nos encontremos en la serie dada.
Veamos en la imagen la distribución de valores y la fórmula que responde a dicho patrón:


La fórmula en concreto es:
=SI(Y(SUMA($B$2:B2)<>0;SUMA($B$2:B2)=B2);B1;"")
que arrastramos hacia la derecha, hasta el final del rango dado. Fijémosnos en que el rango queda cerrado en forma relativa por la derecha, y absoluta (fija) por la izquierda; para que según arrastramos hacia la derecha, dicha referencia se mueva y vaya incluyendo los nuevos valores a la suma acumulada.
La condición que determina la primera posición, esto es, el primer valor diferente a cero, lo he construido como el primer acumulado diferente a cero y que, además, coincida con el valor inicial. En caso de cumplimiento la fórmula devuelve el día (o posición) de la coincidencia.
El resto es sencillo, ya que añado en la celda AG2 una suma del rango así obtenido, en base a ese condicional:
=SUMA(B3:AE3)
obteniendo el día concreto.

En este caso la idea fundamental para dar con la solcuión correcta es tener muy claro cuál y cómo debo contruir la condición.

Esta es una manera de llegar a un resultado correcto, sin embargo requiere de un rango auxiliar de cálculo. Existe al menos otra manera de conseguir lo mismo, sin emplear rangos auxiliares, utilizando una función personalizada en VBA.
Para ello, insertamos el siguiente código VBA en un módulo del Explorador de proyectos VBA:

Function germinacion(rng As Range)
'definimos constantes
suma = 0
x = 0

'La función se actualizará cuando se efectúe un cálculo en alguna celda de la hoja
'en la que aparezca nuestra función.
Application.Volatile

'recorremos el rango seleccionado
For Each celda In rng
'acumulamos valores del rango
suma = suma + celda.Value
x = x + 1
    'localizamos el punto en el que se dan las condiciones de primer día de germinados
    If celda.Value <> 0 And suma = celda.Value Then
    dia = x
    End If
Next celda

'devolvemos el valor obtenido
germinacion = dia

End Function


Vemos en la siguiente imagen cómo el resultado de esta función es el mismo, evitando celdas auxiliares de cálculo. Aunque el proceso y condiciones son idénticas:

Fórmula para localizar un punto de un rango de Excel.

lunes, 5 de noviembre de 2012

Extraer valores de un alfanumérico y sumarlo en Excel.

Veremos una matricial que nos ayudará a poder sumar 'valores' con una parte de texto añadida, es decir, alfanuméricos.
Daré respuesta a una lectora del blog que planteaba esta cuestión:


...no se sumar una serie de números con texto,en este caso kilómetros:
789 km
589 km
698 km...

Aquí el problema es claro, y es que al contener valores numéricos junto a una parte de texto, Excel reconoce la celda como de 'texto', lo que la convierte en inoperable... es como si quisieramos sumar palabras.
Veamos el planteamiento:

Extraer valores de un alfanumérico y sumarlo en Excel.


El trabajo para llegar a obtener el sumatorio de ese rango de celdas 'de texto', consistirá en primer lugar eliminar la parte de texto, que coincide en todas nuestras celdas con ' km'. Ojo, por que estamos eliminando también el espacio en blanco entre el número y el texto 'km'.
Lo que quede de esa eliminación, que conseguimos con la función SUSTITUIR, la convertimos en número, aplicándole la función VALOR. Al resultado numérico obtenido ya es posible aplicarle la función SUMA.
Si trabajamos sobre todo el rango al tiempo, de forma matricial, nuestra fórmula queda entonces:
=SUMA(VALOR(SUSTITUIR(A1:A3;" km";"")))

Extraer valores de un alfanumérico y sumarlo en Excel.


Con lo que obtenemos el resultado de sumar únicamente la parte numérica de cada cela.

jueves, 1 de noviembre de 2012

Contruir un modelo Simplex de programación lineal en Excel con Solver.

Debido a la recurrencia en las peticiones de ayuda a la hora de resolver planteamientos con Solver, he decidido escribir una nueva entrada en la que explicar, no tanto la configuración de la herramienta Solver, si no cómo estructurar el modelo en la hoja de Excel, previa a la ejecución de esta herramienta.
Emplearé un ejemplo planteado por un lector del blog:

...Resuelva utilizando el Método Simplex el siguiente PL.

Maximizar Z = 4X1 +3X2 +6X3

s.a.
3X1 +X2 +3X3 <= 30

2X1 +2X2 + 3X3 <= 40

X1 , X2 , X3 >= 0

Voy a emplear Excel 2010, aunque las explicaciones son perfectamente válidas para cualquier versión de Excel. En esencia se trata de aprender a construir, o más bien trasladar/plantear en la hoja de cálculo, la función objetivo y algunas de las restricciones.
Por supuesto lo primero que debemos tener muy claro son las restricciones y nuestra función objetivo. En nuestro ejemplo es sencillo, ya que nos la dan directamente y no las tenemos que interpretar de ningún texto.
Como tenemos tres variables, dispondremos de tres celdas asociadas que nos devolverán la solución buscada. En nuestra configuración de Solver serán las celdas cambiantes.

Contruir un modelo Simplex de programación lineal en Excel con Solver.


En el siguiente paso construiremos una fórmula que replique nuestra función objetivo y cada una de las restricciones del modelo:

Contruir un modelo Simplex de programación lineal en Excel con Solver.


Podemos ver como los pasos son sencillos, tratamos nuestras las celdas B1, B2 y B3 en las fórmulas como si fueran las variables x1, x2 y x3... y para nuestro modelo lo son.
Ya tenemos asociadas celdas cambiantes (nuestras variables) con el resto de fórmulas generadas (función objetivo y restricciones), asi que estamos preparados para ejecutar Solver. Desde la ficha Datos > Análisis > Solver abrimos la ventana de la herramienta:

lunes, 29 de octubre de 2012

Cursos Excel y Macros - Excelforo - noviembre 2012.

Comienza una nueva edición de Cursos de Excel y Macros en modalidad elearning (online), donde podrás disfrutar y aprender de un nuevo curso que te ofrezco:

Curso Tablas dinámicas en Excel (Nuevo!!!)

(ver más)

Curso Excel Avanzado para versiones 2007/2010

(ver más)

Curso Macros Iniciación

(ver más)

Curso Macros Medio

(ver más)

Curso preparación MOS Excel 2010 (Examen 77-882)

(ver más)


Esta nueva edición de Cursos de Excel y macros en modalidad elearning (online) dará comienzo el próximo día 1 de noviembre de 2012.
Con la confianza de siempre....Anímate!!


Informarte sin compromiso en cursos@excelforo.com o directamente en www.excelforo.com.

En próximas ediciones un nuevo curso Excelforo: Curso Excel para contables-financieros

viernes, 26 de octubre de 2012

VBA: El objeto OLEObject en macros de Excel.

Toca hoy aprender un poco más sobre los controles ActiveX y la forma de interactuar con ellos. En particular hablaré del objeto OLEObject. Hay que saber que este objeto representa un control ActiveX o un objeto OLE (incrustado o vinculado) en una hoja de cálculo.
Probablemente lo sepamos, pero un control ActiveX de una hoja tiene dos nombres: el nombre de la forma que contiene el control, visible en el cuadro Nombre al ver la hoja, y el nombre en código del control, presente en la celda situada a la derecha de (Name) en la ventana Propiedades.


Veamos un ejemplo de aplicación de este objeto. En la Hoja1 de nuestro libro tenemos dispuestos varios controles, algunos son controles de formulario y otros controles ActiveX y también alguna autoforma; entre ellos existen controles de toda clase, pero en concreto hay varios controles tipo CommandButton. Esto son lo que nos interesan, y en particular aquellos con el texto en su Caption 'Excel', escrito de cualquier manera (sin distinguir entre mayúsculas y minúsculas).

VBA: El objeto OLEObject en macros de Excel.



Insertaremos en la hoja del Explorador de proyectos del Editor de VBA el siguiente código, asociado al CommandButton de fondo rojo de nuestra hoja (que hemos llamado, i.e., con Name = CommandButtonIdentifica) formando nuestra macro de Excel:

Private Sub CommandButtonIdentifica_Click()
Dim ctrl As OLEObject
Dim boton As CommandButton

'Recorre los objetos de la hoja de cálculo
For Each ctrl In Worksheets(1).OLEObjects
    'Typeof identifica el tipo de objeto, en nuestro ejemplo exclusivamente no sinteresan los CommandButton
    If TypeOf ctrl.Object Is CommandButton Then
    'Enmascaramos el objeto identificado en una variable de tipo botón para poder manipular sus propiedades
    Set boton = ctrl.Object
    'Identificamos los botones cuyo texto(Caption) sea 'Excel' para deshabilitarlos, ocultarlos, o lo que queramos
    If LCase(boton.Caption) = "excel" Then
    'Dependiendo de la propiedad que quieras manipular, deberás acceder a ella o bien por el objeto botón o bien por el objeto control
    'Si las propiedades Enabled y Locked están ambas como True,
    'el control puede recibir el enfoque y se muestra en formato normal (no atenuado) en el formulario.
    'El usuario puede copiar, pero no editar, los datos del control.
    boton.Enabled = True
    boton.Locked = True
    ctrl.Visible = True
    'para ssegurarnos fácilmente que la macro corre adecuadamente, le asignamos al CommnandButton un color de fondo Ciano
    boton.BackColor = vbCyan
    End If
    End If
Next
End Sub


Si presionamos el botón rojo, en el que hemos incluido mediante el evento _click nuestra macro, obtendríamos:

VBA: El objeto OLEObject en macros de Excel.


Como esperábamos la macro sólo ha afectado a los CommandButton con un Caption 'Excel'.

miércoles, 24 de octubre de 2012

VBA: Macro para abrir y cerrar un libro de Excel - Workbooks.Open.

Explicaré hoy una sencilla macro que nos permite trabajar sobre libros de trabajo en Excel cerrados, pero de los que necesitamos copiar parte de su contenido.
Para ello emplearemos el método Open del objeto Workbooks: WorkBooks.Open; ojo no confundir con otro objeto que es Workbook.
De igual forma para cerrar un libro podemos emplear el método Close del objeto Workbooks: WorkBooks.Close.

Estos dos métodos son la esencia de nuestra futura macro. Macro de Excel que nos permitirá abrir un libro cerrado desde nuestro fichero de trabajo, para seleccionar un rango de celdas, pegarlo en nuestro destino y finalmente cerrarlo.

Supongamos dos ficheros, uno principal (Principal.xlsm) donde pegaremos el contenido del segundo fichero origen (Origen.xlsx). Lógicamente el 'Principal' tiene una extensión .xlsm por que contiene el código de nuestra macro.
Veamos nuestros ficheros de trabajo. El libro 'Origen.xlsx' en su hoja 'Datos' contiene un listado de cursos de Excel:

VBA: Macro para abrir y cerrar un libro de Excel - Workbooks.Open.


Por otro lado queremos pegar los datos existentes de esos cursos de Excel en la hoja 'Resumen' del libro 'Principal.xlsm', pero sólo copiaremos los datos de la tabla excluyendo la cabecera de rótulos, ya que ese dato lo tenemos en nuestro destino.

VBA: Macro para abrir y cerrar un libro de Excel - Workbooks.Open.


Además, para futuros copiados y pegados, la celda destino de nuestro pegado debería ser la primera sin utilizar; por ejemplo, en este primer caso, la primera celda o fila sin utilizar es la que está debajo de la cabecera, esto es celda A2, pero en la siguiente sería la celda A22.

Nuestro código VBA deberá insertarse en un módulo del libro 'Principal.xlsm':

Sub CompletarLibro()
Dim ruta As String, direccion1 As String
Dim celdadestino As Range
'definimos rutas y archivos como variables
ruta = "E:\excelforo\"
fichero1 = "Origen.xlsx"
direccion1 = ruta & fichero1

'identificamos la celda disponible en el archivo Principal, hoja Resumen
Set celdadestino = Workbooks("Principal.xlsm").Sheets("Resumen").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
'abrimos el fichero desde donde copiar... con el método .Open
Workbooks.Open Filename:=direccion1
Worksheets("Datos").Activate
'seleccionamos qué copiar y donde
Set tbl = Range("A1").CurrentRegion
'con este código únicamente copiamos la tabla excepto la primera fila
'y lo pegamos en la celda destino correcta del libro Principal.xlsm
tbl.Offset(1, 0).Resize(tbl.Rows.Count - 1, tbl.Columns.Count).Copy _
Destination:=Workbooks("Principal.xlsm").Sheets("Resumen").Range(celdadestino.Address)
'limpiamos el Portapapeles
Application.CutCopyMode = False
'cerramos fichero origen con el método .Close, sin guardar cambios (nos aseguramos...)
Workbooks(fichero1).Close savechanges:=False

End Sub


Podemos probar nuestra macro de Excel. Para ello cerramos el libor 'Origen.xlsx' y ejecutamos la macro 'CompletarLibro' desde 'Principla.xlsm'. Con ello conseguimos lo esperado, hemos seleccionado del libro 'Origen.xlsx' todas las filas menos la cabecera de la tabla de Cursos y se ha pegado en el libro 'Principal.xlsm' a partir de la primera celda libre:

lunes, 22 de octubre de 2012

VBA: UpdateLink - Actualizar vínculos en Excel.

Son muchas las veces que me consultan sobre la forma de Actualizar vínculos externos en nuestras hojas de Excel. Sabemos que disponemos de la herramienta de Edición de vínculos (ver), desde la cual podemos actualizar nuestros valores siempre que lo necesitemos.
Esta herramienta está pensada para aplicarla en aquellos casos que tenemos vínculos con otros libros de trabajo (en nuestro PC o en red) y que se encuentran cerrados, puesto que si estuvieran abiertos no se haría necesario forzar esa actualización.

Así que centrémonos, tenemos al menos dos libros de trabajo diferentes, en uno de ellos el origen de datos (VinculosOrigen.xlsx) y en otro el destino (VinculosDestino.xlsx), como vemos en la siguiente imagen:

Actualizar vínculos en Excel.



Si cerramos el libro VinculosDestino.xlsx y cambiamos nuestra celda de referencia, y cerramos y guardamos este libro origen. La siguiente vez que abramos el libro destino VinculosOrigen.xlsx, aparecerá por defecto un mensaje adviertiendo de la existencia de vínculos, y preguntando si es nuestro deseo actualizarlos:

Actualizar vínculos en Excel.


La celda vinculada no se actualizará hasta que Habilitemos esta opción. Es posible evitar esta pregunta, y que el libro automáticamente actualice al abrir los vínculos existentes. Para ello iremos a la ficha Datos > Conexiones > Editar vínculos, se abrirá una ventana diálogo, y en esta presionaremos el botón Pregunta inicial, y entre las tres opciones desplegadas, elegiríamos la de No mostrar la alerta y actualizar vínculos:

jueves, 18 de octubre de 2012

Curso Tablas dinámicas en Excel.

Comienza una nueva edición de Cursos de Excel y Macros en modalidad elearning (online), donde podrás disfrutar y aprender de un nuevo curso que te ofrezco:

Curso Tablas dinámicas en Excel (Nuevo!!!)

(ver más)


Por supuesto podrás seguir formándote con los demás cursos que imparto...

Curso Excel Avanzado para versiones 2007/2010

(ver más)

Curso Macros Iniciación

(ver más)

Curso Macros Medio

(ver más)

Curso preparación MOS Excel 2010 (Examen 77-882)

(ver más)


Esta nueva edición de Cursos de Excel y macros en modalidad elearning (online) dará comienzo el próximo día 1 de noviembre de 2012.
Con la confianza de siempre....Anímate!!


El programa del nuevo curso Tablas dinámicas en Excel es el siguiente, pero puedes informarte sin compromiso en cursos@excelforo.com o directamente en www.excelforo.com:

TEMA 1 - INTRODUCCIÓN TABLAS DINÁMICAS
1. Introducción.
2. Terminología de las tablas dinámicas.
3. Generando una tabla dinámica.
4. El panel lista de campos.
5. Extraer información resumida.
TEMA 2 - MENÚ OPCIONES
1. Introducción.
2. Menú opciones.
3. Nombre y opciones de la tabla dinámica.
1. Opciones.
2. Mostrar páginas de filtros de informes.
3. Generar GetPivotData.
4. Campo activo y la configuración de campo.
1. Descripción de campo activo.
2. Configuración del campo valor.
3. Configuración de campos de filas, columnas y filtros.
4. Expandir y contraer todo el campo.
5. Agrupar selección.
6. Ordenar y filtrar.
1. Ordenar y filtrar.
2. Segmentación de datos.
7. Datos.
1. Actualizar.
2. Cambiar origen de datos.
8. Acciones.
9. Cálculos.
10. Herramientas.
11. Mostrar u ocultar.
TEMA 3 - MENÚ DISEÑO
1. Introducción.
2. Menú diseño.
3. Diseño.
4. Opciones de estilo de tabla dinámica.
5. Estilos de tabla dinámica.
TEMA 4 - PRIMERA TABLA DINÁMICA
1. Introducción.
2. Primer paso: El origen de datos.
3. Segundo paso: Insertar el informe de tabla dinámica.
4. Tercer paso: Estructurar la tabla dinámica.
5. Cuarto paso: Agrupar campos.
6. Quinto paso: Configurar opciones.
7. Sexto paso: Diseño de la tabla dinámica.
8. Una conexión a una base de datos (Access).
TEMA 5 - SEGMENTACIÓN DE DATOS
1. Introducción.
2. Crear una segmentación.
3. Opciones de segmentación.
4. Compartir segmentaciones de datos entre td.
5. Desconectar y eliminar segmentaciones.
TEMA 6 - GRÁFICOS DINÁMICOS
1. Introducción.
2. Maneras de crear un gráfico dinámico.
3. Diseño del gráfico dinámico.
4. Menú Presentación.
5. Menú Formato.
6. Menú Analizar.
TEMA 7 - INDICADORES
1. Introducción.
2. Repaso de reglas de Formato condicional.
3. El formato condicional en una tabla dinámica.
4. Ejemplo de Formato condicional en una tabla dinámica.
5. Los Minigráficos.
6. Minigráficos aplicados a una tabla dinámica.
7. Ejemplo de un Minigráfico asociado a una tabla dinámica.
TEMA 8 - ASISTENTE TABLAS DINÁMICAS 2003
1. Introducción.
2. El asistente de tablas dinámicas 2003.
3. Rangos de consolidación múltiples.
3.1. Asistente para tablas dinámicas con un solo campo de página.
3.2. Asistente para tablas dinámicas con varios campos de página.
4. Peculiaridades de una tabla dinámica con rangos de consolidación múltiple.
5. Tablas dinámicas independientes.
TEMA 9 - FILTROS Y ORDENACIÓN
1. Introducción.
2. Mover elementos dentro de un campo.
3. La ordenación de elementos.
3.1. Ordenar elementos de un campo de fila/columna.
3.2. Ordenar elementos de un campo de valor.
4. Filtros de campo.
4.1. Filtro de informe para mostrar elementos.
4.2. Filtro manual de elementos de campos de etiquetas de filas/columnas.
4.3. Filtrar elementos aplicando un filtro de etiqueta.
4.4. Filtrar elementos aplicando un filtro de valor.
4.5. Filtrar elementos aplicando un filtro de fecha.
4.6. Filtro para mostrar los 10 elementos superiores o inferiores.
4.7. Filtrar por selección para mostrar u ocultar solo los elementos seleccionados.
4.8. Quitar filtros.
TEMA 10 - MOSTRAR VALORES COMO
1. Introducción.
2. Mostrar valores como: % del total general.
3. Mostrar valores como: % del total de columnas.
4. Mostrar valores como: % del total de filas.
5. Mostrar valores como: % de...
6. Mostrar valores como: % del total de filas principales.
7. Mostrar valores como: % del total de columnas principales.
8. Mostrar valores como: % del total principal….
9. Mostrar valores como: diferencia de….
10. Mostrar valores como: % de la diferencia de….
11. Mostrar valores como: total en….
12. Mostrar valores como: % del total en.
13. Mostrar valores como: clasificar de menor a mayor.
14. Mostrar valores como: clasificar de mayor a menor.
15. Mostrar valores como: índice.
TEMA 11 - CAMPOS Y ELEMENTOS CALCULADOS
1. Introducción.
2. Otras herramientas de los campos y elementos calculados.
3. Editar campos y elementos calculados.
4. Eliminar campos y elementos calculados.
5. Campos calculados.
6. Elementos calculados.
7. Fórmulas en gráficos dinámicos.
8. Algo más sobre fórmulas en tablas dinámicas.