Создание файла Excel с информацией из базы данных - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть запрос, который возвращает что-то вроде этого:

1    2    3    4    5    6    7
A.   B.   C.   D.   E.   F.   G.
Etc...
Etc...
N rows

Я сохраняю запрос в наборе данных.Затем я создаю файл Excel, используя что-то вроде этого:

Sql=“select * from table”
Dim cmd As New SqlDataAdapter(Sql, con)
Dim ds As New DataSet
cmd.Fill(ds)

For i=0 To Tables(0).Rows.Count - 1
    For x=0 To ds.Tables(0).Columns.Count - 1
        ExcelFile.Cells(i+1;x+1)=ds.Tables(0).Rows(i).Item(j)
    Next
Next

Код работает нормально, за исключением того, что мне нужно написать также имя заголовка столбца (1,2,3,4 и т. Д.) Мой первый вопрос очередиэто как добавить заголовки?

И главная проблема ... запрос иногда возвращает более 80 тыс. Результатов, поэтому, следуя логике цикла for, мой код будет выполняться 80 тыс. Раз для каждого столбца (в данном случае 7 раз), чтособирается дать мне медленный результат.

Есть еще один быстрый способ заполнить и файл Excel?Или это лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

У вас есть доступ к ColumnName свойству каждого Column в вашем DataTable.Например, чтобы просто добавить заголовки с как можно меньшим изменением вашего кода, вы можете просто сделать следующее:

'Write ColumnName to the corresponding cell in row 1
For x=0 To ds.Tables(0).Columns.Count - 1
    ExcelFile.Cells(1, x+1) = ds.Tables(0).Columns(x).ColumnName
Next

'Modded to start at the second row and fix index variable
For i=1 To Tables(0).Rows.Count - 1
    For x=0 To ds.Tables(0).Columns.Count - 1
        ExcelFile.Cells(i+1, x+1) = ds.Tables(0).Rows(i).Item(x)
    Next
Next

Вы правы, если будете обеспокоены производительностью этого.Правило номер один в автоматизации Excel заключается в том, чтобы фактически взаимодействовать с Excel как можно меньше, потому что каждое взаимодействие очень дорого.

Предполагая, что вы используете обычное взаимодействие Office, вы должны построить двумерный массив, представляющий значения из вашего запроса.Затем вы находите эквивалентный диапазон размеров в своей рабочей таблице и устанавливаете значение этого диапазона в массив.Таким образом, вы сократили многие тысячи взаимодействий до одного.

Dim rowCount = ds.Tables(0).Rows.Count
Dim colCount = ds.Tables(0).Columns.Count

Dim ws = ExcelFile

Dim valueSet(,) As Object
ReDim valueSet(rowCount - 1, colCount - 1)

For row = 0 To rowCount - 1
    For col = 0 To colCount - 1
        valueSet(row, col) = ds.Tables(0).Rows(row).Item(col)
    Next
Next

'Set the entire set of values in a single operation
ws.Range(ws.Cells(1, 0), ws.Cells(rowCount, colCount).Value = valueSet

Кроме того, если вы на самом деле используете Excel Interop или обертку вокруг него, например NetOffice , вам следует изучить EPPlus и посмотрите, делает ли он то, что вам нужно.Это вспомогательная библиотека, которая работает с OfficeOpenXML и даже не требует установки Excel.

0 голосов
/ 05 декабря 2018

Я использую следующее:

Dim sSql As String
Dim tbl As ListObject

'Declare a Connection object
Dim cnDB As New ADODB.Connection

'Declare a Recordset Object
Dim rs As ADODB.Recordset

' Housekeeping, set the connection strings
Set cnn = New ADODB.Connection
cnn.Provider = "MSDASQL"
cnn.CommandTimeout = 100

Set tbl = ActiveSheet.ListObjects("Lookup")
With tbl.DataBodyRange
    If .Rows.Count > 1 Then
        .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count).Rows.Delete
    End If
End With

' Connect to the database and paste new data
cnn.ConnectionString = "driver={};server={};uid={};pwd={};database={}"
sSql = "SELECT BLAH BLAH "
cnn.Open
Set rs = cnn.Execute(sSql)

ThisWorkbook.Worksheets("Lookup").Range("A2").CopyFromRecordset rs
cnn.Close
...