Usuário com melhor resposta
Utilizando o Office Web Component

Pergunta
-
Pessoal, estou querendo gerar relatórios na minha aplicação ASP.NET em excel, porém esses relatórios irão abrir arquivos modelos em .xls, preencher os valores e depois disponibilizar para download.
Minha primeira tentativa foi utilizar o Microsoft.Office.Interop.Excel.Application, ele funcionou porém depois que acaba todo o processo (mesmo dando um nothing no final) o Excel.exe continua na memória e não consegui tirar ele de lá.
Ví que existe o Office Web Component, parece que ele funciona da mesma forma porém não consegui abrir o arquivo .xls para poder atualizar os valores.
Alguém sabe me dizer como eu faço isso?
Obrigado.
Respostas
-
Wagner,
Veja abaixo o código da applicação Web aqui da empresa que funciona exportando dados para o Excel.
Public Function ExportaDados(ByVal pHostAddress As String, ByVal pIdeUni As Double, ByVal pIdePlaGes As Double, ByVal pBuscaAvancada As cFiltroGestaoRisco.stcBuscaAvancada) As String Try Dim strReturnPath As String = String.Empty Dim lExcel As New Excel.Application Dim lBooks As Excel.Workbooks Dim lBook As Excel.Workbook Dim lSheets As Excel.Sheets Dim lSheet As Excel.Worksheet Dim lCells As Excel.Range Try 'String.Format("{0}\TmpExcel\TmpExcel.xls", pHostAddress) Dim lDir As New System.IO.DirectoryInfo(String.Format("{0}arquivos\GestaoRiscos", pHostAddress)) If lDir.Exists Then For Each lFile As System.IO.FileInfo In lDir.GetFiles If lFile.CreationTime < DateTime.Today Then lFile.Delete() Next Else : System.IO.Directory.CreateDirectory(String.Format("{0}arquivos\GestaoRiscos", pHostAddress)) End If Dim lFileName As String = String.Empty Select Case Avaliacao Case eRiscos.Ambiental lFileName = Resources.Resource.Ambientais Case eRiscos.Saude + eRiscos.SegurancaOcupacional lFileName = Resources.Resource.Ocupacionais Case eRiscos.Financeira lFileName = Resources.Resource.Financeiros Case eRiscos.Operacional lFileName = Resources.Resource.Operacionais Case eRiscos.ParteInteressada lFileName = Resources.Resource.PartesInteressadas End Select Dim lTemplatePath As String = String.Format("{0}Templates\GestaoRiscos\{1} - {2}.xls", pHostAddress, Resources.Resource.GestaoDeRiscos, lFileName) 'Caminho do arquivo Template strReturnPath = String.Format("{0}arquivos\GestaoRiscos\Tmp{1}_{2}.xls", pHostAddress, lFileName, DateTime.Now.ToString().Replace("/", String.Empty).Replace(":", String.Empty).Replace(" ", String.Empty)) lExcel.Visible = False lExcel.DisplayAlerts = False 'Start a new workbook lBooks = lExcel.Workbooks 'Carrega o arquivo de template lBooks.Open(lTemplatePath) 'Pega o primeiro Workbook lBook = lBooks.Item(1) 'Carrega as planilhas do arquivo lSheets = lBook.Worksheets 'Pega a primeira planilha do arquivo lSheet = CType(lSheets.Item(1), Excel.Worksheet) 'Seta o nome da planilha lSheet.Name = String.Format("{0} {1}", Resources.Resource.Riscos, lFileName) 'Carreta as células da planilha lCells = lSheet.Cells 'Setando as linhas da planilha Me.OpenDataReader(Me.RetornaRiscosPorAplicacao(pIdeUni, pIdePlaGes, pBuscaAvancada, True)) Select Case Avaliacao Case eRiscos.Ambiental PreencheCelulasAmbiental(lCells) Case eRiscos.Saude + eRiscos.SegurancaOcupacional PreencheCelulasOcupacional(lCells) Case eRiscos.Financeira PreencheCelulasFinanceiro(lCells) Case eRiscos.Operacional PreencheCelulasOperacional(lCells) Case eRiscos.ParteInteressada PreencheCelulasPartesInteressadas(lCells) End Select lCells.Columns.AutoFit() 'Salva arquivo lSheet.SaveAs(strReturnPath) Catch ex As Exception Throw ex Finally lBook.Close() 'Finaliza o Excel e desaloca os objetos lExcel.Quit() ReleaseComObject(lCells) : ReleaseComObject(lSheet) ReleaseComObject(lSheets) : ReleaseComObject(lBook) ReleaseComObject(lBooks) : ReleaseComObject(lExcel) lExcel = Nothing : lBooks = Nothing : lBook = Nothing lSheet = Nothing : lCells = Nothing : lSheets = Nothing 'Coletor de lixo System.GC.Collect() End Try Return strReturnPath Catch ex As Exception Throw ex End Try End Function
Pode ser porque no seu código você não esta chamando o método Quit do objeto Excel.
E também usamos o método ReleaseComObject da classe Marshal do .Net.
E depois chamamos o GC por precaução.
Espero ter ajudado.
Douglas Aguiar
MCAD, MCT- Sugerido como Resposta Douglas Aguiar quinta-feira, 5 de novembro de 2009 12:56
- Marcado como Resposta Harley Araujo sexta-feira, 6 de novembro de 2009 13:03
Todas as Respostas
-
Wagner,
O Office Web Components é um controle ActiveX que roda no browser do usuário, e funciona de uma forma completamente diferente que o VSTO.
Na minha empresa utilizamos o VSTO em uma aplicação Web e tivemos o mesmo problema que você. Este problema ocorre por a aplicação Web roda no servidor com privilegios reduzidos ai ela não consegue fechar o Excel e as vezes nem abri-lo, mesmo que você use uma conta com mais privilegios fazendo um impersonate no momento de manipular o Excel.
Dai partimos para uma outra alternativa, criamos um serviço windows que fica verificando uma pasta, assim que um arquivo Excel cai nesta pasta o serviço manipula o arquivo e joga para uma outra pasta onde minha aplicação Web recupera o arquivo já processado e o envia para o usuário.
Espero ter ajudado.
Douglas Aguiar
MCAD, MCT- Sugerido como Resposta Douglas Aguiar quinta-feira, 5 de novembro de 2009 00:49
-
Olá Douglas, obrigado por responder.
O problema do excel não sair da lista dos processos, a meu ver não tem a ver com permissão (pelo menos no meu caso) porque se eu criar uma aplicação windows forms o processo também fica preso na memória. Não sei se tem a ver por o componente ser COM e não ser gerenciado.
Você tem algum exemplo de utilização do VSTO com excel?
Obrigado. -
Wagner,
Veja abaixo o código da applicação Web aqui da empresa que funciona exportando dados para o Excel.
Public Function ExportaDados(ByVal pHostAddress As String, ByVal pIdeUni As Double, ByVal pIdePlaGes As Double, ByVal pBuscaAvancada As cFiltroGestaoRisco.stcBuscaAvancada) As String Try Dim strReturnPath As String = String.Empty Dim lExcel As New Excel.Application Dim lBooks As Excel.Workbooks Dim lBook As Excel.Workbook Dim lSheets As Excel.Sheets Dim lSheet As Excel.Worksheet Dim lCells As Excel.Range Try 'String.Format("{0}\TmpExcel\TmpExcel.xls", pHostAddress) Dim lDir As New System.IO.DirectoryInfo(String.Format("{0}arquivos\GestaoRiscos", pHostAddress)) If lDir.Exists Then For Each lFile As System.IO.FileInfo In lDir.GetFiles If lFile.CreationTime < DateTime.Today Then lFile.Delete() Next Else : System.IO.Directory.CreateDirectory(String.Format("{0}arquivos\GestaoRiscos", pHostAddress)) End If Dim lFileName As String = String.Empty Select Case Avaliacao Case eRiscos.Ambiental lFileName = Resources.Resource.Ambientais Case eRiscos.Saude + eRiscos.SegurancaOcupacional lFileName = Resources.Resource.Ocupacionais Case eRiscos.Financeira lFileName = Resources.Resource.Financeiros Case eRiscos.Operacional lFileName = Resources.Resource.Operacionais Case eRiscos.ParteInteressada lFileName = Resources.Resource.PartesInteressadas End Select Dim lTemplatePath As String = String.Format("{0}Templates\GestaoRiscos\{1} - {2}.xls", pHostAddress, Resources.Resource.GestaoDeRiscos, lFileName) 'Caminho do arquivo Template strReturnPath = String.Format("{0}arquivos\GestaoRiscos\Tmp{1}_{2}.xls", pHostAddress, lFileName, DateTime.Now.ToString().Replace("/", String.Empty).Replace(":", String.Empty).Replace(" ", String.Empty)) lExcel.Visible = False lExcel.DisplayAlerts = False 'Start a new workbook lBooks = lExcel.Workbooks 'Carrega o arquivo de template lBooks.Open(lTemplatePath) 'Pega o primeiro Workbook lBook = lBooks.Item(1) 'Carrega as planilhas do arquivo lSheets = lBook.Worksheets 'Pega a primeira planilha do arquivo lSheet = CType(lSheets.Item(1), Excel.Worksheet) 'Seta o nome da planilha lSheet.Name = String.Format("{0} {1}", Resources.Resource.Riscos, lFileName) 'Carreta as células da planilha lCells = lSheet.Cells 'Setando as linhas da planilha Me.OpenDataReader(Me.RetornaRiscosPorAplicacao(pIdeUni, pIdePlaGes, pBuscaAvancada, True)) Select Case Avaliacao Case eRiscos.Ambiental PreencheCelulasAmbiental(lCells) Case eRiscos.Saude + eRiscos.SegurancaOcupacional PreencheCelulasOcupacional(lCells) Case eRiscos.Financeira PreencheCelulasFinanceiro(lCells) Case eRiscos.Operacional PreencheCelulasOperacional(lCells) Case eRiscos.ParteInteressada PreencheCelulasPartesInteressadas(lCells) End Select lCells.Columns.AutoFit() 'Salva arquivo lSheet.SaveAs(strReturnPath) Catch ex As Exception Throw ex Finally lBook.Close() 'Finaliza o Excel e desaloca os objetos lExcel.Quit() ReleaseComObject(lCells) : ReleaseComObject(lSheet) ReleaseComObject(lSheets) : ReleaseComObject(lBook) ReleaseComObject(lBooks) : ReleaseComObject(lExcel) lExcel = Nothing : lBooks = Nothing : lBook = Nothing lSheet = Nothing : lCells = Nothing : lSheets = Nothing 'Coletor de lixo System.GC.Collect() End Try Return strReturnPath Catch ex As Exception Throw ex End Try End Function
Pode ser porque no seu código você não esta chamando o método Quit do objeto Excel.
E também usamos o método ReleaseComObject da classe Marshal do .Net.
E depois chamamos o GC por precaução.
Espero ter ajudado.
Douglas Aguiar
MCAD, MCT- Sugerido como Resposta Douglas Aguiar quinta-feira, 5 de novembro de 2009 12:56
- Marcado como Resposta Harley Araujo sexta-feira, 6 de novembro de 2009 13:03
-