none
Eliminar archivo de Excel después de mandarlo por correo RRS feed

  • Pregunta

  • Buen dia

    me pueden ayudar con este problema, tengo un reporte que se genera al exportar un grid a excel, pero no lo muestro solo lo guardo en una carpeta, luego ese reporte se envía por correo, después de enviarlo mando una instrucción para eliminar ese archivo de excel pero me muestra el siguiente error:

    El proceso no puede obtener acceso al archivo 'C:\Reportes\2016051755.xlsx' porque está siendo utilizado en otro proceso.

    aqui esta el codigo:

      Private Sub btnGuardar_Click(sender As Object, e As EventArgs) Handles btnGuardar.Click
            exportar()
            EnviaCorreo("correo@mail.com", "Prueba Requisicion 1", "va la reqisicion", "C:\Reportes\" & idReq)
            File.Delete("C:\Reportes\" & idReq & ".xlsx")
        End Sub
    
        Private Sub exportar()
    
            Dim app As Microsoft.Office.Interop.Excel._Application = New Microsoft.Office.Interop.Excel.Application()
            Dim workbook As Microsoft.Office.Interop.Excel._Workbook = app.Workbooks.Add("C:\Plantilla\Requisicion.xlsx")
            Dim worksheet As Microsoft.Office.Interop.Excel._Worksheet = Nothing
            worksheet = workbook.Sheets("Solicitud")
            worksheet = workbook.ActiveSheet
    
            For i As Integer = 0 To Me.dgvDetalle.Rows.Count - 1
                worksheet.Cells(i + 16, 2) = Me.dgvDetalle.Rows(i).Cells(0).Value
                worksheet.Cells(i + 16, 5) = Me.dgvDetalle.Rows(i).Cells(1).Value
                worksheet.Cells(i + 16, 8) = Me.dgvDetalle.Rows(i).Cells(2).Value
                worksheet.Cells(i + 16, 13) = Me.dgvDetalle.Rows(i).Cells(3).Value
            Next
    
            'Aqui se guarda el documento de excel
            app.ActiveWorkbook.SaveAs("C:\Reportes\" & idReq)
      
            'Mto los procesos de excel
            app = Nothing
            workbook = Nothing
            worksheet = Nothing
    
            FileClose(1)
            GC.Collect()
        End Sub
    
        Public Function EnviaCorreo(ByVal Para As String, ByVal Asunto As String, ByVal Mensaje As String, ByVal Adjunto As String) As Integer
    
            Dim _Message As New System.Net.Mail.MailMessage()
            Dim _SMTP As New System.Net.Mail.SmtpClient
            Dim att As New System.Net.Mail.Attachment(Adjunto & ".xlsx")
    
            'CONFIGURACIÓN DEL STMP
            _SMTP.Credentials = New System.Net.NetworkCredential(Correo_, Contraseña)
            _SMTP.Host = ServidorSalida
            _SMTP.Port = Puerto
            _SMTP.EnableSsl = True
    
            ' CONFIGURACION DEL MENSAJE
            _Message.[To].Add(Para.ToString) 'Cuenta de Correo al que se le quiere enviar el e-mail
            _Message.From = New System.Net.Mail.MailAddress(Correo_, Firma, System.Text.Encoding.UTF8) 'Quien lo envía
            _Message.Subject = Asunto.ToString 'Sujeto del e-mail
            _Message.SubjectEncoding = System.Text.Encoding.UTF8 'Codificacion
            _Message.Body = Mensaje.ToString 'contenido del mail
            _Message.BodyEncoding = System.Text.Encoding.UTF8
            _Message.Priority = System.Net.Mail.MailPriority.Normal
            _Message.Attachments.Add(att)
            _Message.IsBodyHtml = True
    
            'ENVIO
            Try
                ServicePointManager.ServerCertificateValidationCallback = Function(s As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) True
                _SMTP.Send(_Message)
    
                Return 1
            Catch ex As System.Net.Mail.SmtpException
                Return 2
                ' MessageBox.Show(ex.ToString, "Error!", MessageBoxButtons.OK)
            End Try
        End Function

    si se genera el archivo de excel, también se envía por correo, solo no puedo eliminar el archivo.

    espero y me puedan ayudar, de antemano gracias.


    Eduardo Rivera

    martes, 17 de mayo de 2016 14:51

Respuestas

  • "Lalo_Rivera" escribió:

    > ... después de enviarlo mando una instrucción para eliminar ese archivo
    > de excel pero me muestra el siguiente error:
    >
    > El proceso no puede obtener acceso al archivo 'C:\Reportes\2016051755.xlsx'
    > porque está siendo utilizado en otro proceso.
    >
    > aqui esta el codigo:
    >
    >  'Mto los procesos de excel
    >  app = Nothing
    >  workbook = Nothing
    >  worksheet = Nothing
    >
    >  FileClose(1)
    >  GC.Collect()

    Hola:

    Así no se "mata" el proceso de Excel, aunque ejecutes una recolección de elementos no utilizados, ya que el proceso de Excel continúa "vivo y coleando" al no haber llamado a su método Quit, de ahí que obtengas el error a la hora de eliminar el archivo de Excel.

    >  FileClose(1)

    Digo yo que para cerrar un archivo con el procedimiento FileClose aquel tiene que haber sido abierto con la función FileOpen, ambas pertenecientes al espacio de nombres Microsoft.VisualBasic, por lo que aquí creo que sobra la llamada a FileClose.

    >  worksheet = workbook.Sheets("Solicitud")
    >  worksheet = workbook.ActiveSheet

    Aquí deberás elegir entre una de las dos maneras de referenciar un objeto Excel.Worksheet, por lo que en el ejemplo de abajo me decido por referenciar una hoja llamada Solicitud.

    Prueba a ejecutar el código del procedimiento Exportar como indico a continuación:

        Private Sub Exportar()
    
            Dim app As New Microsoft.Office.Interop.Excel.Application()
            Dim workbook As Microsoft.Office.Interop.Excel._Workbook = Nothing
            Dim worksheet As Microsoft.Office.Interop.Excel._Worksheet = Nothing
    
            Try
                workbook = app.Workbooks.Add("C:\Plantilla\Requisicion.xlsx")
                worksheet = DirectCast(workbook.Sheets("Solicitud"), Excel._Worksheet)
                ' worksheet = DirectCast(workbook.ActiveSheet, Excel._Worksheet)
    
                For i As Integer = 0 To Me.dgvDetalle.Rows.Count - 1
                    worksheet.Cells(i + 16, 2) = Me.dgvDetalle.Rows(i).Cells(0).Value
                    worksheet.Cells(i + 16, 5) = Me.dgvDetalle.Rows(i).Cells(1).Value
                    worksheet.Cells(i + 16, 8) = Me.dgvDetalle.Rows(i).Cells(2).Value
                    worksheet.Cells(i + 16, 13) = Me.dgvDetalle.Rows(i).Cells(3).Value
                Next
    
                'Aqui se guarda el documento de excel
                app.ActiveWorkbook.SaveAs("C:\Reportes\" & idReq)
    
            Finally
                'Mto los procesos de excel
                If (Not worksheet Is Nothing) Then
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(worksheet)
                    worksheet = Nothing
                End If
    
                If (Not workbook Is Nothing) Then
                    ' Cerramos el libro de Excel.
                    workbook.Close()
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook)
                    workbook = Nothing
                End If
    
                If (Not app Is Nothing) Then
                    ' Cerramos Excel.
                    app.Quit()
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app)
                    app = Nothing
                End If
    
                ' FileClose(1) --> SOBRA
    
                ' Si observas que el proceso de Excel continua estando
                ' en el Administrador de tareas, ejecuta entonces una
                ' recolección de elementos no utilizados.
                '
                ' GC.Collect()
                ' GC.WaitForPendingFinalizers()
    
            End Try
    
        End Sub
    

    Como indico en los comentarios, solamente necesitas ejecutar una recolección de elementos no utilizados si observas que continúas obteniendo el mismo mensaje de error a la hora de eliminar el archivo de Excel.

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    • Marcado como respuesta Lalo_Rivera martes, 17 de mayo de 2016 18:40
    martes, 17 de mayo de 2016 15:46
    Moderador
  • "Lalo_Rivera" escribió:

    > Si se elimina al omitir la funcion EnviarCorreo

    Entonces podemos descartar que el motivo del error no se debe al proceso de Excel.

    Como en tu mensaje inicial escribiste "... también se envía por correo", daba por hecho que la función EnviaCorreo se ejecutaba satisfactoriamente. Pero si no es así, y al no DESTRUIR los objetos que en ella utilizas, puede ser que el archivo adjunto se quede "pillado".

    En el bloque Try ... End Try, inserta el bloque Finally para llamar a los métodos Dispose de los tres objetos que utilizas:

            Catch ex As System.Net.Mail.SmtpException
                Return 2
                'MessageBox.Show(ex.ToString, "Error!", MessageBoxButtons.OK)
    
            Finally
                att.Dispose()
                _Message.Dispose()
                _SMTP.Dispose()
    
            End Try

    En negrita el código que tienes que insertar.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    martes, 17 de mayo de 2016 17:53
    Moderador

Todas las respuestas

  • "Lalo_Rivera" escribió:

    > ... después de enviarlo mando una instrucción para eliminar ese archivo
    > de excel pero me muestra el siguiente error:
    >
    > El proceso no puede obtener acceso al archivo 'C:\Reportes\2016051755.xlsx'
    > porque está siendo utilizado en otro proceso.
    >
    > aqui esta el codigo:
    >
    >  'Mto los procesos de excel
    >  app = Nothing
    >  workbook = Nothing
    >  worksheet = Nothing
    >
    >  FileClose(1)
    >  GC.Collect()

    Hola:

    Así no se "mata" el proceso de Excel, aunque ejecutes una recolección de elementos no utilizados, ya que el proceso de Excel continúa "vivo y coleando" al no haber llamado a su método Quit, de ahí que obtengas el error a la hora de eliminar el archivo de Excel.

    >  FileClose(1)

    Digo yo que para cerrar un archivo con el procedimiento FileClose aquel tiene que haber sido abierto con la función FileOpen, ambas pertenecientes al espacio de nombres Microsoft.VisualBasic, por lo que aquí creo que sobra la llamada a FileClose.

    >  worksheet = workbook.Sheets("Solicitud")
    >  worksheet = workbook.ActiveSheet

    Aquí deberás elegir entre una de las dos maneras de referenciar un objeto Excel.Worksheet, por lo que en el ejemplo de abajo me decido por referenciar una hoja llamada Solicitud.

    Prueba a ejecutar el código del procedimiento Exportar como indico a continuación:

        Private Sub Exportar()
    
            Dim app As New Microsoft.Office.Interop.Excel.Application()
            Dim workbook As Microsoft.Office.Interop.Excel._Workbook = Nothing
            Dim worksheet As Microsoft.Office.Interop.Excel._Worksheet = Nothing
    
            Try
                workbook = app.Workbooks.Add("C:\Plantilla\Requisicion.xlsx")
                worksheet = DirectCast(workbook.Sheets("Solicitud"), Excel._Worksheet)
                ' worksheet = DirectCast(workbook.ActiveSheet, Excel._Worksheet)
    
                For i As Integer = 0 To Me.dgvDetalle.Rows.Count - 1
                    worksheet.Cells(i + 16, 2) = Me.dgvDetalle.Rows(i).Cells(0).Value
                    worksheet.Cells(i + 16, 5) = Me.dgvDetalle.Rows(i).Cells(1).Value
                    worksheet.Cells(i + 16, 8) = Me.dgvDetalle.Rows(i).Cells(2).Value
                    worksheet.Cells(i + 16, 13) = Me.dgvDetalle.Rows(i).Cells(3).Value
                Next
    
                'Aqui se guarda el documento de excel
                app.ActiveWorkbook.SaveAs("C:\Reportes\" & idReq)
    
            Finally
                'Mto los procesos de excel
                If (Not worksheet Is Nothing) Then
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(worksheet)
                    worksheet = Nothing
                End If
    
                If (Not workbook Is Nothing) Then
                    ' Cerramos el libro de Excel.
                    workbook.Close()
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook)
                    workbook = Nothing
                End If
    
                If (Not app Is Nothing) Then
                    ' Cerramos Excel.
                    app.Quit()
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app)
                    app = Nothing
                End If
    
                ' FileClose(1) --> SOBRA
    
                ' Si observas que el proceso de Excel continua estando
                ' en el Administrador de tareas, ejecuta entonces una
                ' recolección de elementos no utilizados.
                '
                ' GC.Collect()
                ' GC.WaitForPendingFinalizers()
    
            End Try
    
        End Sub
    

    Como indico en los comentarios, solamente necesitas ejecutar una recolección de elementos no utilizados si observas que continúas obteniendo el mismo mensaje de error a la hora de eliminar el archivo de Excel.

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    • Marcado como respuesta Lalo_Rivera martes, 17 de mayo de 2016 18:40
    martes, 17 de mayo de 2016 15:46
    Moderador
  • Muchas gracias por responder Enrique.

    me sigue marcando el mismo error, ya puse el codigo correcto para exportar (gracias por corregirlo).

    el problema debe de estar al momento de buscar el archivo guardado para mandarlo por correo en la funcion EnviaCorreo, no libera el archivo para despues eliminarlo, ahi no se que hacer, que proceso matar o como liberarlo


    Eduardo Rivera

    martes, 17 de mayo de 2016 16:37
  • "Lalo_Rivera" escribió:

    > me sigue marcando el mismo error,...
    >
    > el problema debe de estar al momento de buscar el archivo guardado
    > para mandarlo por correo en la funcion EnviaCorreo, no libera el
    > archivo para despues eliminarlo, ahi no se que hacer, que proceso
    > matar o como liberarlo

    ¡Vamos a ver! Lo primero que tienes que hacer es verificar si se ELIMINA CORRECTAMENTE el archivo de Excel una vez creado. Para salir de dudas si se debe o no al código de la función EnviaCorreo, prueba a eliminar el archivo SIN LLAMAR a la función EnviaCorreo:

      Private Sub btnGuardar_Click(sender As Object, e As EventArgs) Handles btnGuardar.Click
    
            Exportar()
     
    ' NO EJECUTAR POR AHORA --> EnviaCorreo("correo@mail.com", "Prueba Requisicion 1", "va la reqisicion", "C:\Reportes\" & idReq) File.Delete("C:\Reportes\" & idReq & ".xlsx") End Sub

    Dime si se elimina el archivo o continuas recibiendo el error.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    martes, 17 de mayo de 2016 17:20
    Moderador
  • Si se elimina al omitir la funcion EnviarCorreo

    Eduardo Rivera

    martes, 17 de mayo de 2016 17:30
  • "Lalo_Rivera" escribió:

    > Si se elimina al omitir la funcion EnviarCorreo

    Entonces podemos descartar que el motivo del error no se debe al proceso de Excel.

    Como en tu mensaje inicial escribiste "... también se envía por correo", daba por hecho que la función EnviaCorreo se ejecutaba satisfactoriamente. Pero si no es así, y al no DESTRUIR los objetos que en ella utilizas, puede ser que el archivo adjunto se quede "pillado".

    En el bloque Try ... End Try, inserta el bloque Finally para llamar a los métodos Dispose de los tres objetos que utilizas:

            Catch ex As System.Net.Mail.SmtpException
                Return 2
                'MessageBox.Show(ex.ToString, "Error!", MessageBoxButtons.OK)
    
            Finally
                att.Dispose()
                _Message.Dispose()
                _SMTP.Dispose()
    
            End Try

    En negrita el código que tienes que insertar.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    martes, 17 de mayo de 2016 17:53
    Moderador
  • Enrique eres un genio, si funciono con lo del "Finally", muchas gracias  por tu ayuda, ahora todo esta jalandoa la perfeccion

    Eduardo Rivera

    martes, 17 de mayo de 2016 18:30
  • "Lalo_Rivera" escribió:

    > ... si funciono con lo del "Finally", muchas gracias por tu ayuda,
    > ahora todo esta jalandoa la perfeccion

    Me alegro que se haya solucionado el problema. Pero si no hubieras arreglado también el proceso de Excel que te indiqué en mi primera respuesta, te aseguro que tampoco podrías eliminar el archivo de Excel, ya que ni estabas cerrando Excel (ejecutar su método Quit) ni tampoco estabas liberando los objetos utilizados, por lo que entiendo que la primera respuesta también se puede considerar como correcta. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    martes, 17 de mayo de 2016 18:34
    Moderador