jueves, febrero 12, 2015

Copiar suma de varias celdas a una única celda como valor

Cada post que publico lleva por lo menos una etiqueta que identifica el contenido. A lo largo del tiempo he creado muchas etiquetas, como puede verse en la nube de etiquetas en la columna derecha del blog (o izquierda, si es que se me da por cambiar la plantilla).
Para este post debiera haber creado una nueva etiqueta, algo así como "técnicas complicadas para resolver problemas no tan graves existiendo otras técnicas más sencillas". Pero como resulta un poco largo seguramente terminaré endosándole la lacónica etiqueta "Macros".

La situación es la siguiente: en una hoja de Excel hay datos numéricos "desparramados" en varias celdas; la misión es sumar todos los valores y poner el resultado en una única celda. Esta celda debe contener un valor constante, no una fórmula. A los efectos del ejemplo uso una única hoja; el problema real comprendía varias hojas.

¿Cuáles son las opciones?
  1. Tomar un papel y un lápiz, hacer la cuenta y teclear el resultado.
  2. Totalizar los datos en una celda, copiar el resultado y pegarlo en la celda indicada como valor.
  3. Usar una macro para agilizar el proceso.
La primera opción es una broma. El problema con la segunda opción es lo tedioso del proceso.

Nos queda así la opción de la macro, que es la que utilice al enfrentarme con el problema.

El código de la macro es la siguiente

Sub copy_and_sum()
    Dim rngCell As Range, dblTemp As Double
    Dim dblTotSum As New DataObject

    For Each rngCell In Selection
        If IsNumeric(rngCell) Then
            dblTemp = dblTemp + rngCell
        End If
    Next rngCell


    With dblTotSum
        .SetText dblTemp
        .PutInClipboard
    End With

End Sub

Para utilizar la macro comenzamos por seleccionar las celdas que queremos totalizar (clic a la primer celda y Ctrl-Clic a las restantes); luego activamos la macro (con ALT-F8 o un atajo de teclado); la macro suma los valores numéricos de las celdas y copia el total al Clipboard. Finalmente usamos Ctrl-V o Pegar para pegar el valor en la celda correspondiente.



Esta macro usa el objeto DataObject por lo que hay que activar la referencia al Microsoft Forms 2.0 Object Library.


A pesar de que este objeto está definido para copiar texto al Clipboard, podemos ver que también lo hará con valores numéricos y lo que es más importante, nos permitirá ir sumándolos.

En la primera parte del código usamos un loop For Each Next para asignar los valores numéricos a la variable dblTemp e ir sumándolos. En la segunda parte del código empezamos por asignar el valor de dblTemp al objeto dblTotSum para luego copiarlo al Clipboard con el método PutinClipboard.

lunes, febrero 09, 2015

Seleccionar celdas combinadas en una hoja de Excel

En más de un post me he explayado sobre ese mal hábito de usar "combinar y centrar" en las hojas de Excel. También he expuesto más de una vez las ventajas de usar "centrar en la selección" en su lugar.

No siempre podemos evitar el uso de "combinar y centrar", ya sea porque el rango a unificar es vertical (no exste la posibilidad de "centrar en la selección" verticalmente) o porque estamos lidiando con un cuaderno que recibimos de algún colega.

Si queremos "descombinar" todos los rangos combinados en una hoja, podemos seleccionar todas las celdas de la hoja (Ctrl-E o clic en el cuadrdado a la izquierda y arriba de A1) y pulsar el botón "Combinar y centrar". Si queremos reemplazar el "combinar y centrar" por el "centrar en la selección", podemos usar la macro que aparece en el post mencionado.

Si queremos marcar los rangos de celdas combinadas en una hoja de Excel, podemos usar esta macro. Las áreas combinadas aparecerán con fondo rojo; por supuesto, podemos adaptar el código para dar cualquier otro formato (por ejemplo, borde)

Sub mark_merged_cells()

    Dim rngSearchArea As Range, rngCell As Range

    Set rngSearchArea = Range(Cells(1, 1), _
                        Range(Cells.SpecialCells(xlCellTypeLastCell).Address))

    For Each rngCell In rngSearchArea
        If rngCell.MergeCells = True Then
            rngCell.Interior.Color = 190
        End If
    Next rngCell

End Sub
Sub select_merged_cells()




Si queremos sólo seleccionar las áreas combinadas, usamos esta macro

Sub select_merged_cells()
 
    Dim rngSearchArea As Range, rngCell As Range
    Dim rngTemp As Range
 
    Set rngSearchArea = Range(Cells(1, 1), _
                        Cells.SpecialCells(xlCellTypeLastCell).Address)
 
    For Each rngCell In rngSearchArea
        If rngCell.MergeCells = True Then
            If rngTemp Is Nothing Then
                Set rngTemp = rngCell
            Else
                Set rngTemp = Union(rngTemp, rngCell)
            End If
        End If
    Next rngCell
 
    rngTemp.Select
 
End Sub



En ambas macros definimos el área de búsqueda desde la celda A1 hasta la última celda usada en la hoja (para evitar que la macro corra por toda la eternidad) con 

Set rngSearchArea = Range(Cells(1, 1), Range(Cells.SpecialCells(xlCellTypeLastCell).Address))

Para seleccionar simultáneamente los distintos rangos en la segunda macro, usamos el método Union. 





jueves, enero 29, 2015

Cálculo de tiempos y formato personalizado en Excel

Ayer apareció por mi oficina Armando, del departamento de planificación. Me llamó la atención que llegara solo porque, por lo general, se lo ve con Raquel, la del departamento de producción (las malas lenguas dicen que...).

- Como seguramente sabés, los datos de uso de las máquinas están en minutos.
- Si, lo se.
- ¿Cómo hago para mostrarlos en días, horas y minutos?
- Poniendo el formato correspondiente. Digamos "dd hh:mm"
- No sabía que existía ese formato, no aparece en la lista.
- Es un formato personalizado.
- Ah!, gracias.

Como era de esperar, Armando apareció de nuevo a los pocos minutos.

- Mirá, tu método no funciona; en lugar de 1 día, 22 horas y 40 minutos, me da este resultado


- ¿Te acordás lo que te explique sobre cómo Excel calcula fechas y horas? Tenes que dividir los 2800 minutos por 1440.

- Pero, ¿por qué 1440?
- Porque tu dato está en  minutos, y en un día hay 1440 minutos (60 x 24). Como explicaba en esa nota, que parece ser no leiste, los días en Excel están representados por una serie de números enteros y las horas, minutos y segundos por la parte decimal. Así 1 es un día, una hora es 1/24 (0.466667), un minuto es 1/1440 y un segundo es 1/86400 (24 x 60 x 60). Fijate en esta tabla


- Entendido, gracias. Pero cómo hago para que se entienda que se trata de días/horas/minutos. Si te fijas en la celda D3 de tu tabla parece ser 1 hora, no un día.
- Agregando texto en el formato personalizado; por ejemplo dd "dias" hh "horas y" mm "minutos". Fijate en esta tabla


- ¿Y si quiero que cuando sea un día aparezca "01 día" y no en plural?
- Usando formato condicional con esta regla



El formato condicional se suma al formato de la celda. Si queremos aplicar lo mismo para las horas y los minutos tenemos que crear un formato condicional para cada caso.