Могу ли я импортировать INTO excel из источника данных без итерации? - PullRequest
3 голосов
/ 20 сентября 2010

В настоящее время у меня есть приложение, которое берет информацию из базы данных SQLite и помещает ее в Excel. Однако мне нужно взять каждый DataRow, перебрать каждый элемент, поместить каждое значение в его собственную ячейку и определить выделение. Это вызывает 20 минут, чтобы экспортировать файл записи 9000 в Excel. Я уверен, что это можно сделать быстрее, чем это. Я думаю, что я мог бы использовать источник данных для заполнения диапазона Excel, а затем использовать заголовки столбцов и номера строк для форматирования только тех строк, которые необходимо отформатировать. Однако, когда я смотрю в Интернете, что бы я ни печатал, он всегда показывает примеры использования Excel в качестве базы данных, а не импорта в Excel. Если я не забыл ключевое слово или. Теперь эту функцию нужно выполнять в коде, поскольку она является частью более крупного приложения. В противном случае я бы просто подключил Excel к БД и извлек сам информацию. К сожалению, это не так. Буду признателен за любую информацию, которая может помочь мне в быстрой загрузке листа Excel. Спасибо.

Дополнительная информация:
Еще одна причина, по которой необходимо извлекать информацию из БД в коде, заключается в том, что не на каждом компьютере, на котором она загружена, будет работать Excel Это. Лицо, использующее приложение, может просто попросить экспортировать данные и отправить их по электронной почте своему руководителю. Приложение настройки включает в себя необходимые библиотеки для приложения в правильном формате.

Пример кода (текущий):

    For Each strTemp In strColumns
        excelRange = worksheet.Cells(1, nCounter)
        excelRange.Select()
        excelRange.Value2 = strTemp
        excelRange.Interior.Color = System.Drawing.Color.Gray.ToArgb()
        excelRange.BorderAround(Excel.XlLineStyle.xlContinuous, Excel.XlBorderWeight.xlThin, Excel.XlColorIndex.xlColorIndexAutomatic, Type.Missing)
        nCounter += 1
    Next

Теперь, это только пример кода с точки зрения итерации, которую я делаю. Там, где я действительно обрабатываю информацию из базы данных, я перебираю строки DataTable, затем перебираю элементы в dataRow и делаю по сути то же самое, что и выше; значение по значению, выбирая диапазон и помещая значение в ячейку, форматируя ячейку, если она является частью отчета (не всегда серой), и переходя к следующему набору данных. То, что я хотел бы сделать, это поместить все данные в таблицу Excel (A2: ??, не строка, а несколько строк), а затем выполнить итерации по отчетам и отформатировать каждую строку. Таким образом, единственный раз, когда я перебираю все записи, это когда каждая запись является частью отчета.

Идеальный код

excelRange = worksheet.Cells("A2", "P9000")
excelRange.DataSource = ds 'ds would be a queried dataSet, and I know there is no excelRange.DataSource.
'Iteration code to format cells

Обновление:

Я знаю, что мои примеры были на VB, но это потому, что я также пытался написать VB-версию приложения, так как мой босс предпочитает VB. Тем не менее, вот мой окончательный код с использованием набора записей. Функция ConvertToRecordset была получена из здесь .

        private void CreatePartSheet(Excel.Worksheet excelWorksheet)
        {
            _dataFactory.RevertDatabase();
            excelWorksheet.Name = "Part Sheet";
            string[] strColumns = Constants.strExcelPartHeaders;
            CreateSheetHeader(excelWorksheet, strColumns);

            System.Drawing.Color clrPink = System.Drawing.Color.FromArgb(203, 192, 255);
            System.Drawing.Color clrGreen = System.Drawing.Color.FromArgb(100, 225, 137);

            string[] strValuesAndTitles = {/*...Column Names...*/};

            List<string> lstColumns = strValuesAndTitles.ToList<string>();

            System.Data.DataSet ds = _dataFactory.GetDataSet(Queries.strExport);
            ADODB.Recordset rs = ConvertToRecordset(ds.Tables[0]);
            excelRange = excelWorksheet.get_Range("A2", "ZZ" + rs.RecordCount.ToString());
            excelRange.Cells.CopyFromRecordset(rs, rs.RecordCount, rs.Fields.Count);
            int nFieldCount = rs.Fields.Count;

            for (int nCounter = 0; nCounter < rs.RecordCount; nCounter++)
            {
                int nRowCounter = nCounter + 2;
                List<ReportRecord> rrPartReports = _lstReports.FindAll(rr => rr.PartID == nCounter).ToList<ReportRecord>();
                excelRange = (Excel.Range)excelWorksheet.get_Range("A" + nRowCounter.ToString(), "K" + nRowCounter.ToString());
                excelRange.Select();
                excelRange.NumberFormat = "@";

                if (rrPartReports.Count > 0)
                {
                    excelRange.Interior.Color = System.Drawing.Color.FromArgb(230, 216, 173).ToArgb(); //Light Blue

                    foreach (ReportRecord rr in rrPartReports)
                    {
                        if (lstColumns.Contains(rr.Title))
                        {
                            excelRange = (Excel.Range)excelWorksheet.Cells[nRowCounter, lstColumns.IndexOf(rr.Title) + 1];
                            excelRange.Interior.Color = rr.Description.ToUpper().Contains("TAG") ? clrGreen.ToArgb() : clrPink.ToArgb();

                            if (rr.Description.ToUpper().Contains("TAG"))
                            {
                                rs.Find("PART_ID=" + (nCounter + 1).ToString(), 0, ADODB.SearchDirectionEnum.adSearchForward, "");
                                excelRange.AddComment(Environment.UserName + ":  " + _dataFactory.GetTaggedPartPrevValue(rs.Fields["POSITION"].Value.ToString(), rr.Title));
                            }
                        }
                    }
                }

                if (nRowCounter++ % 500 == 0)
                {
                    progress.ProgressComplete = ((double)nRowCounter / (double)rs.RecordCount) * (double)100;
                    Notify();
                }
            }

            rs.Close();

            excelWorksheet.Columns.AutoFit();
            progress.Message = "Done Exporting to Excel";
            Notify();
            _dataFactory.RestoreDatabase();
        }

Ответы [ 6 ]

2 голосов
/ 20 сентября 2010

В Excel есть возможность записать все данные из набора записей ADO или DAO за одну операцию, используя метод CopyFromRecordset .

Фрагмент кода:

    Sheets("Sheet1").Range("A1").CopyFromRecordset rst
2 голосов
/ 20 сентября 2010

Можете ли вы использовать ODBC?

''http://www.ch-werner.de/sqliteodbc/

dbName = "c:\docs\test"
scn = "DRIVER=SQLite3 ODBC Driver;Database=" & dbName _
& ";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"

Set cn = CreateObject("ADODB.Connection")
cn.Open scn

Set rs = CreateObject("ADODB.Recordset")
rs.Open "select * from test", cn

Worksheets("Sheet3").Cells(2, 1).CopyFromRecordset rs

Кстати, Excel вполне доволен HTML и внутренними таблицами стилей.

2 голосов
/ 20 сентября 2010

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

Обновление: Существует также ряд библиотек (бесплатных и коммерческих), которые могут упростить создание документа Excel, например excellibrary , который еще не поддерживает новый формат.В ответах на Создание файла Excel (.XLS и .XLSX) из C #

упоминаются другие.
1 голос
/ 20 сентября 2010

Я бы обычно рекомендовал использовать Excel для извлечения данных из SQLite. Используйте Excel "Другие источники данных". Затем вы можете выбрать своего поставщика OLE DB, использовать строку подключения, что у вас. alt text

Однако звучит так, что реальным значением вашего кода является форматирование ячеек, а не передача данных.

Возможно, рефакторинг процесса:

  • имеет Excel импортировать данные
  • используйте свой код, чтобы открыть электронную таблицу Excel, и примените форматирование

Я не уверен, является ли это подходящим набором процессов для вас, но, возможно, что-то стоит рассмотреть?

0 голосов
/ 20 сентября 2010

Возможно, разместите некоторый код, и мы сможем отследить любые проблемы.

Я бы рассмотрел эту цепочку событий:

  • запрос базы данных SQLite для вашего набора данных.
  • переместить данные из объектов ADO.NET в объекты POCO.Прекратите использовать DataTables / Rows.
  • используйте For Each для вставки в Excel.
0 голосов
/ 20 сентября 2010
...