Este artículo explica cómo exportar las horas asignadas a cada recurso en Microsoft Project día por día a Microsoft Excel en un formato que permita crear una tabla pívot.
Realicé las siguientes búsquedas en Internet sin resultado:
- Exportar MS Project día por día
- Export MS Project in daily basis
- Microsoft Project export timescaled
Finalmente me enteré que MS Project no incluye esta función y, en caso de necesitarla, había que programarla en VBA (Visual Basic for Applications).
Problema
Cuando exportamos los datos a otro formato, Microsoft Project crea un registro por cada tarea asignada a cada recurso y esta tarea incluye los datos de fecha de inicio de la tarea, fecha de finalización y cantidad de horas que la tarea requiere. Esto significa que, si una tarea comienza el día 1 y requiere 60 horas, sólo obtendremos un registro con esos datos. Cuando hacemos la tabla pívot, crearemos un reporte en el que dice que el recurso trabajará 60 horas el día 1 y ninguna los días siguientes.
Lo que necesitamos exportar son los datos que representan la vista de “Resource Usage”

En mi caso particular debía exportar los datos desde un archivo Project que funciona como “Resource Pool”. La particularidad de este archivo es que no contiene tareas, sólo recursos y asignaciones.
Solución
Primero debemos abrir el entorno de VBA para crear la nueva macro con la combinación de teclas ALT + F11.

Creé un nuevo formulario llamado “frmExportTimescaled” dentro de “ProjectGlobal (Global.MPT)”. Esto significa que la macro estará disponible para cualquier archivo de Project que abramos.
Armamos la interfaz de usuario con fecha inicial, fecha final, tipo de datos a exportar, dos barras de progreso (una para recursos y otro para asignaciones) y un botón para exportar.
Para poder agregar los controles “Date Time Picker” primero debemos ir al menú Tools -> References y agregar “Microsoft Windows Common Controls 2 (MSCOMCT2.OCX)”. Si no tenemos esta librería, la pueden obtener desde http://activex.microsoft.com/controls/vb6/mscomct2.cab
Luego vamos al menú Tools -> Additional Controls y seleccionar “Microsoft Date and Time Picker Control 6.0” para agregarlo al Toolbox.
Los nombres que les puse a los controles para referenciarlos desde código son:
- Start Date: sDate
- End Date: eDate
- Type of data: ddAssignType
- Label resources: lblResources
- Resources progress bar: pBarResources
- Label assignments: lblAssign
- Assignment progress bar: pBarAssignments
- Export button: btnExport
Para poder poblar la lista de tipos de datos y para crear un botón con nuestra macro en una barra de herramientas de Project, creamos un nuevo módulo (yo le puse por nombre Export_Timescaled). Este módulo, además de poblar los tipos de datos, invoca al formulario.
El siguiente es el código del módulo Export_Timescaled:
Sub Export_Timescaled()
frmExportTimescaled.ddAssignType.Clear
frmExportTimescaled.ddAssignType.AddItem ("Work")
frmExportTimescaled.ddAssignType.AddItem ("Actual Work")
frmExportTimescaled.ddAssignType.AddItem ("Cumularive Work")
frmExportTimescaled.ddAssignType.AddItem ("Overallocation")
frmExportTimescaled.ddAssignType.AddItem ("Cost")
frmExportTimescaled.Show
End Sub
El siguiente es el código del formulario frmExportTimescaled:
Option Explicit
Dim xlApp As Excel.Application
Private Sub btnExport_Click()
Dim t As Task
Dim Asgn As Assignment
Dim a As Integer
Dim b As Integer
Dim currRow As Integer
Dim i As Double
Dim c As Range
Dim TSV As TimeScaleValues
Dim AssignType As PjAssignmentTimescaledData
Call ControlsEnable(False) 'Disable all form controls
Call CreateExcelFile
Application.ActiveWindow.Refresh 'This makes form get focus
Set c = xlApp.ActiveCell
currRow = 0
'Set column titles
c.Offset(currRow, 0) = "Task Name"
c.Offset(currRow, 1) = "Employee"
c.Offset(currRow, 2) = "Date"
c.Offset(currRow, 3) = "Hours"
c.Offset(currRow, 4) = "Week"
Call InitProgressBarResources(ActiveProject.Resources.Count)
'Determine Assignment Type to export
Select Case ddAssignType.Value
Case "Actual Work":
AssignType = PjAssignmentTimescaledData.pjAssignmentTimescaledActualWork
Case "Cumularive Work":
AssignType = PjAssignmentTimescaledData.pjAssignmentTimescaledCumulativeWork
Case "Overallocation":
AssignType = PjAssignmentTimescaledData.pjAssignmentTimescaledOverallocation
Case "Cost":
AssignType = PjAssignmentTimescaledData.pjAssignmentTimescaledCost
Case Else
AssignType = PjAssignmentTimescaledData.pjAssignmentTimescaledWork
End Select
For a = 1 To ActiveProject.Resources.Count
pBarResources.Value = a 'Update progress bar
lblResources.Caption = a & "/" & pBarResources.Max 'Update label
If Not ActiveProject.Resources.Item(a) Is Nothing And ActiveProject.Resources.Item(a).Assignments.Count > 0 Then
Call InitProgressBarAssing(ActiveProject.Resources.Item(a).Assignments.Count) 'Initialize second progress bar
For b = 1 To ActiveProject.Resources.Item(a).Assignments.Count
If Not ActiveProject.Resources.Item(a).Assignments.Item(b) Is Nothing Then
Set TSV = ActiveProject.Resources.Item(a).Assignments(b).TimeScaleData(sDate.Value, eDate.Value + 1, AssignType, pjTimescaleDays)
pBarAssignments.Value = b 'Update second progress bar
lblAssign.Caption = b & "/" & pBarAssignments.Max 'Update second label
For i = 1 To TSV.Count
DoEvents
If IsNumeric(TSV.Item(i).Value) Then 'Check for data
currRow = currRow + 1
c.Offset(currRow, 0) = ActiveProject.Resources.Item(a).Assignments.Item(b).TaskName
c.Offset(currRow, 2) = ActiveProject.Resources.Item(a).Name
c.Offset(currRow, 3) = TSV.Item(i).StartDate
c.Offset(currRow, 4) = Round(TSV.Item(i).Value / 60, 2)
c.Offset(currRow, 5) = DateAdd("d", 5 - (Weekday(TSV.Item(i).StartDate, vbSunday)), TSV.Item(i).StartDate)
End If
Next
End If
Next
End If
Next
MsgBox ("Exportación completa")
ControlsEnable True
End Sub
Sub ControlsEnable(status As Boolean)
btnExport.Enabled = status
sDate.Enabled = status
eDate.Enabled = status
ddAssignType.Enabled = status
End Sub
Sub InitProgressBarResources(cant As Integer)
pBarResources.Min = 0
pBarResources.Max = cant
pBarResources.Value = 0
End Sub
Sub InitProgressBarAssing(cant As Integer)
pBarAssignments.Min = 0
pBarAssignments.Max = cant
pBarAssignments.Value = 0
End Sub
Sub CreateExcelFile()
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim a As Integer
'Create Excel Object
Set xlApp = New Excel.Application
xlApp.Visible = True
AppActivate "Microsoft Excel"
'Create Workbooks and Output Sheet
Set xlBook = xlApp.Workbooks.Add
Set xlSheet = xlBook.Worksheets.Add
'Create Sheet name. Must be less than 31 characters
xlSheet.Name = Mid(Mid(ActiveProject.Name, 1, Len(ActiveProject.Name) - 4) & " (" & ddAssignType.Value & ")", 1, 31)
'Delete extra sheets
For a = 1 To 3
xlBook.Worksheets(2).Delete
Next
End Sub
Finalmente, para poder compartir la macro con otras personas, la copié a un archivo de Project vacío utilizando el menú
Tools ->
Organizer, seleccionando “Modules”. De esta forma, abrimos el archivo en otra computadora y copiamos la macro hacia el
Global.MPT y ya queda disponible en nuestro MS Project.
Descargar archivos fuente
Descargar archivo MS Project con la macro
IMPORTANTE
Si al correr la macro aparece el error "User-defined type not defined"

significa que falta la Referencia al objeto Excel dentro de la macro. Para solucionar esto vamos a la pantalla de VBA (ALT+F11), seleccionamos Tools --> References

Y seleccionamos "Microsoft Excel 11.0 Object Library" o similar. Les muestro mis referencias:

Guardamos y ejecutamos la macro nuevamente.