Jhorbam
Jhorbam

Reputation: 23

Getting information from the RESOURCE USAGE view

I have this code in VB .NET and VSTO that accesses a MS Project file and exports the information from the RESOURCE USAGE view to Excel, but when taking the information about the work distributed over time for the resource, it only prints ZEROs (0) from column D onwards (the area selected for this printout).

' ExportacionUsoRecursos.vb
Imports Microsoft.Office.Interop.Excel
Imports Microsoft.Office.Interop.MSProject
Imports System.Windows.Forms
Imports System.Globalization
Imports System.Drawing
Imports Microsoft.Win32
Imports Microsoft.Office.Interop

Public Enum PjResourceTimescaledDataType2
    pjResourceTimescaledWork = 0 ' Trabajo planeado distribuido en el tiempo para recursos
    pjResourceActualWork = 2      ' Trabajo real para recursos
    pjResourceTimescaledBudgetWork = 1172 ' Trabajo presupuestado para recursos
    pjResourceTimescaledBaselineWork = 1  ' Trabajo de línea base para recursos
    pjResourceTimescaledBaselineBudgetWork = 1117 ' Trabajo presupuestado de línea base para recursos
End Enum

Public Enum PjTimescaleUnit2
    pjTimescaleWeeks = 2 ' Escala de tiempo en semanas
End Enum

''' <summary>
''' Clase que exporta los datos de recursos (vista USO DE RECURSOS) a una hoja de Excel ("DatImp").
''' Por cada recurso se genera una fila con:
''' - Nombre de Recurso (columna A)
''' - Trabajo planeado (columna B, convertido de minutos a horas)
''' - Una fórmula de autosuma en la columna C que sume la distribución semanal del trabajo planeado
'''   (desde la columna D en adelante).
''' Los intervalos se determinan a partir de las fechas del proyecto (se usan los mismos intervalos para todos los recursos).
''' Se congela la vista desde la celda D2 y, al finalizar, se cierra MS Project para evitar procesos en segundo plano.
''' </summary>
Public Class ExportacionUsoRecursos

    ''' <summary>
    ''' Exporta a la hoja "DatImp" los datos de recursos y la distribución semanal del trabajo planeado.
    ''' </summary>
    ''' <param name="proj">Objeto Project obtenido vía MS Project Interop.</param>
    Public Sub ExportarRecursosConDistribucion(proj As Project)
        Try
            Dim excelApp As Microsoft.Office.Interop.Excel.Application = Globals.ThisAddIn.Application
            Dim wb As Workbook = excelApp.ActiveWorkbook
            Dim ws As Worksheet = Nothing

            ' Buscar o crear la hoja "DatImp"
            For Each sheet As Worksheet In wb.Worksheets
                If sheet.Name = "DatImp" Then
                    ws = sheet
                    Exit For
                End If
            Next
            If ws Is Nothing Then
                ws = CType(wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count)), Worksheet)
                ws.Name = "DatImp"
            End If

            ' Limpiar contenido previo
            ws.Cells.Clear()

            ' --- Encabezados generales en la fila 1 ---
            ws.Cells(1, 1).Value = "Nombre de Recurso"
            ws.Cells(1, 2).Value = "Trabajo"
            ws.Cells(1, 3).Value = "Autosuma"
            ' Desde la columna D en adelante se imprimirán los intervalos semanales

            ' --- Determinar los intervalos semanales (usando las fechas del proyecto) ---
            Dim projectStart As DateTime = proj.Start
            Dim projectFinish As DateTime = proj.Finish

            ' Ajustar projectStart para que sea un lunes (si no lo es, tomar el siguiente lunes)
            Dim startOfWeek As DateTime = projectStart
            If startOfWeek.DayOfWeek <> DayOfWeek.Monday Then
                Dim daysToAdd As Integer = (CInt(DayOfWeek.Monday) - CInt(startOfWeek.DayOfWeek) + 7) Mod 7
                startOfWeek = startOfWeek.AddDays(daysToAdd)
            End If

            ' Calcular el número de semanas (redondeando hacia arriba)
            Dim numWeeks As Integer = Math.Ceiling((projectFinish - startOfWeek).TotalDays / 7)
            Dim intervalDates As New List(Of DateTime)
            For i As Integer = 0 To numWeeks - 1
                intervalDates.Add(startOfWeek.AddDays(i * 7))
            Next

            ' --- Imprimir la cabecera de intervalos (fechas) a partir de la columna D en la fila 1 ---
            Dim col As Integer = 4 ' Columna D
            For Each intervalDate As DateTime In intervalDates
                ws.Cells(1, col).NumberFormat = "@"  ' Forzar formato de texto
                ws.Cells(1, col).Value = intervalDate.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture)
                col += 1
            Next

            ' --- Desactivar actualización de pantalla y cálculo automático para mejorar el rendimiento ---
            excelApp.ScreenUpdating = False
            excelApp.Calculation = XlCalculation.xlCalculationManual

            Dim currentRow As Integer = 2

            ' Iterar sobre cada recurso en el proyecto
            For Each res As Resource In proj.Resources
                If res IsNot Nothing AndAlso Not String.IsNullOrEmpty(res.Name) Then
                    ' Datos generales para el recurso:
                    ws.Cells(currentRow, 1).Value = res.Name
                    ws.Cells(currentRow, 2).Value = res.Work / 60  ' Convertir minutos a horas

                    ' Para cada intervalo, obtener la distribución del trabajo planeado para el recurso.
                    ' Se usa el período global del proyecto (startOfWeek a projectFinish).
                    col = 4 ' Comenzar en la columna D
                    For Each intervalDate As DateTime In intervalDates
                        Dim intervalEnd As DateTime = intervalDate.AddDays(6)
                        Dim totalWork As Double = 0
                        Try
                            ' Usar el tipo de dato correcto para recursos
                            Dim tsd As TimeScaleValues = res.TimeScaleData(
                                intervalDate, intervalEnd,
                                PjResourceTimescaledDataType2.pjResourceTimescaledWork,
                                PjTimescaleUnit2.pjTimescaleWeeks, 1)
                            If tsd IsNot Nothing AndAlso tsd.Count > 0 Then
                                totalWork = CDbl(tsd(1).Value) / 60 ' Convertir minutos a horas
                            End If
                        Catch ex As System.Exception
                            ' Mensaje de depuración para inspeccionar errores
                            'Debug.WriteLine("Error al obtener datos escalados para el recurso " & res.Name & ": " & ex.Message)
                            totalWork = 0
                        End Try
                        ws.Cells(currentRow, col).Value = totalWork
                        col += 1
                        System.Windows.Forms.Application.DoEvents()
                    Next

                    ' Insertar fórmula de autosuma en la columna C que sume las columnas D hasta la última columna de intervalo
                    Dim firstCell As String = ws.Cells(currentRow, 4).Address(False, False)
                    Dim lastCell As String = ws.Cells(currentRow, 3 + numWeeks).Address(False, False)
                    ws.Cells(currentRow, 3).Formula = "=SUM(" & firstCell & ":" & lastCell & ")"

                    ' (Opcional) Se puede aplicar un color de fondo a la fila, si se desea. Para recursos se usa un color predeterminado.
                    ws.Rows(currentRow).Interior.Color = ColorTranslator.ToOle(Color.LightGray)

                    currentRow += 1
                    If currentRow Mod 10 = 0 Then
                        excelApp.ScreenUpdating = True
                        System.Windows.Forms.Application.DoEvents()
                        excelApp.ScreenUpdating = False
                    End If
                End If
                System.Windows.Forms.Application.DoEvents()
            Next

            excelApp.ScreenUpdating = True
            excelApp.Calculation = XlCalculation.xlCalculationAutomatic

            ws.Activate()
            Dim freezeRange As Range = ws.Range("D2")
            freezeRange.Select()
            excelApp.ActiveWindow.FreezePanes = True

            Dim msProjApp As MSProject.Application = proj.Application
            msProjApp.Quit(MSProject.PjSaveType.pjDoNotSave)
            System.Runtime.InteropServices.Marshal.ReleaseComObject(msProjApp)

            MessageBox.Show("Datos de recursos y Trabajo Presupuestado exportados en la hoja 'DatImp'.",
                            "Exportación de Recursos", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Catch ex As System.Exception
            MessageBox.Show("Error al exportar datos de recursos: " & ex.Message,
                            "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

End Class

What could be wrong with my code?

Upvotes: 0

Views: 35

Answers (0)

Related Questions