#asp.net #excel #vb.net #export-to-excel #excel-interop
Вопрос:
Я пытаюсь экспортировать данные в Excel и получаю следующее исключение при запуске wb.SaveAs(путь):
Exception from HRESULT: 0x800A03EC
Изначально я получал эту ошибку при настройке диапазона рабочего листа. Я исправил это, сделав его ненулевым индексированным. Однако массив данных по-прежнему индексируется с нулевой индексацией.
К сожалению, никаких дополнительных сведений об ошибке не приводится.
Код:
Dim app As New Excel.Application
Dim wb As Excel.Workbook = app.Workbooks.Add()
Dim ws As Excel.Worksheet
Dim strFN As String = "MyFileName.xlsx"
Dim dt As New DataTable
Using da As New DataAdapter(dif)
da.SetSelectCommand(SQL)
da.Fill(dt)
End Using
ws = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
DataTableToExcel(dt, ws, "TableName")
wb.SaveAs(path)
wb.Close()
Private Sub DataTableToExcel(dt As DataTable, ws As Excel.Worksheet, TabName As String)
Dim arr(dt.Rows.Count, dt.Columns.Count) As Object
Dim r As Int32, c As Int32
For r = 0 To dt.Rows.Count - 1
For c = 0 To dt.Columns.Count - 1
arr(r, c) = dt.Rows(r).Item(c)
Next
Next
ws.Name = TabName
c = 0
For Each column As DataColumn In dt.Columns
If column.ColumnName.Length > 4 Then
If column.ColumnName.Substring(column.ColumnName.Length - 4, 4) = "_ID" Then
ws.Cells(1, c 1) = column.ColumnName.Replace("_", " ").Substring(0, column.ColumnName.Length - 4)
Else
ws.Cells(1, c 1) = column.ColumnName.Replace("_", " ")
End If
Else
ws.Cells(1, c 1) = column.ColumnName.Replace("_", " ")
End If
c = 1
Next
ws.Range(ws.Cells(2, 1), ws.Cells(dt.Rows.Count, dt.Columns.Count))(1).Value = arr
End Sub
Обновить:
Мне удалось предотвратить возникновение ошибки, изменив SaveAs() на SaveCopyAs().
Теперь файл экспортируется, но когда я его открываю, там есть только имена столбцов и только первое значение первого столбца/строки.
Комментарии:
1. Пожалуйста, используйте
try/catch
и зафиксируйте полное исключение. Кроме того, попробуйте экспортировать меньше данных с помощью этого кода; возможно, произошла ошибка с содержимым таблицы данных…вы можете поделиться структурой таблицы данных и некоторыми образцами данных?2. Ваш веб-сайт работает как x32 или 64-разрядный? Это сообщение об ошибке выглядит как пропущенный размер бита. Если ваш веб-сайт и проект работают как 64-разрядные, то для этого вам необходимо установить 64-разрядную версию Excel. возможно, вы сможете для тестирования установить свой проект на x86 и попробовать это. Но это может стать проблемой в будущем, так как большинство веб-серверов теперь работают как 64-разрядные. Но попробуйте настроить свой проект с «любого процессора» на проект, работающий под управлением x86. Или вы можете/могли бы попробовать установить 64-разрядную версию Excel
3. @MarcoAurelioFernandezReyes, функция уже находится в состоянии try/catch, то есть полное сообщение об ошибке. К сожалению, я не могу поделиться этими данными, поскольку это данные, которыми я не вправе делиться. Я пробовал экспортировать несколько разных таблиц, иногда отфильтрованных только до одной или двух записей. Я каждый раз получаю одну и ту же ошибку.
4. @AlbertD.Kallal, веб-сайт работает как x64, и версия excel также x64. Я пытался запустить веб-сайт как x86 и получил ту же ошибку.
5. Вместо использования Excel и взаимодействия вы можете использовать одну из многих библиотек, которые генерируют реальные файлы Excel без использования Excel, например Epplus, NPOI или ClosedXML. С помощью, например , Epplus вы можете написать
ws.Cells.LoadFromDataTable(table)
илиLoadFromCollection(someList)
LoadFromDataReader()
заполнить лист из таблицы данных,IEnumerable<T>
илиIDbDataReader
Ответ №1:
Запуск Excel только для экспорта данных в файл Excel является излишним. Для веб-сайтов это совершенно непрактично по нескольким причинам:
- Вам нужна лицензия для каждого пользователя сайта. Это большие деньги.
- Слишком легко оставить Excel открытым, медленно поглощая оперативную память и процессор сервера.
- Это просто слишком медленно
xlsx
это ZIP-пакет, содержащий четко определенные XML-файлы, поэтому их можно создавать напрямую, используя SDK Open XML или одну из многих библиотек с открытым исходным кодом, которые значительно упрощают это, например Epplus, NPOI или ClosedXML.
Например, Epplus позволяет заполнять лист Excel из DataTable, IEnumerable или IDbDataReader одним вызовом:
Dim dt As DataTable = ...
Dim fi New FileInfo(SomePath)
Using p As New ExcelPackage(fi)
Dim ws = p.Workbook.Worksheets.Add(sheetName)
ws.Cells("A1").LoadFromDataTable(dt, PrintHeaders:=True)
p.Save()
End Using
Вы также можете использовать LoadFromDataReader и избежать загрузки всех данных в память:
Using cmd As New SqlCommand(sql,connection)
connection.Open()
Using reader As SqlDataReader = cmd.ExecuteReader()
Dim fi New FileInfo(SomePath)
Using p As New ExcelPackage(fi)
Dim ws = p.Workbook.Worksheets.Add(sheetName)
ws.Cells("A1").LoadFromDataReader(reader, PrintHeaders:=True)
p.Save()
End Using
End Using
End Using