Ускорить выгрузку в excel

Как ускорить выгрузку в эксель?

Я
   zzerro

25.01.11 — 17:24

Тема конечно забитая, но никак не могу увеличить скорость записи в эксель большого объема данных (около 100 тыс строк).

Пробовал через ТабличныйДокумент.Записать(), но насколько я понял 8.1 не может записывать в xlsx, а в формате xls не входит по количесву строк.

Пробовал через Новый COMОбъект(«Excel.Application»), но заполнение файла через Лист.Cells(НомерСтроки, 1).Value = Значение;  работает ужасно медленно, хоть и снимается ограничение по количесву строк, т.к. установлен 2010 офис.

Подскажите, чем еще можно записать данные в эксель, желательно с примером.

   izekia

1 — 25.01.11 — 17:26

можно записать в хмл таблицу с хслт форматированием
минус — не поддерживаются группировки

   Nexux

2 — 25.01.11 — 17:26

через ADO, возможно

   skunk

3 — 25.01.11 — 17:28

2010 само по себе было «снятно» ограничение на количество строк … хотя по факту ограничение есть

   izekia

4 — 25.01.11 — 17:28

(2) получается апдейтить каждую строчку, не медленно получится?

   skunk

5 — 25.01.11 — 17:29

хотя данное ограничение еще 2007 снялось

   skunk

6 — 25.01.11 — 17:30

(4)нет не получается … ну можно ускорить работу самого екселя и по оле … правда не так сильно как с адо …

   mikecool

7 — 25.01.11 — 17:30

(0) присвоение не тормозит обычно, оформляешь наверное тут же при выводе?

   mikecool

8 — 25.01.11 — 17:31

+7 рисовал как то вывод в эксель из 7-ки 8-10 листов по 30-40 тыщ записей
сам вывод — занимал минуты 2-3
оформление — уже массово после вывода

   skunk

9 — 25.01.11 — 17:32

надо отключать в екселе видимость … перерисовку экрана …

   mikecool

10 — 25.01.11 — 17:36

(9) кстати да, важный момент
а насчет оформления после вывода — замерял, производительность вырастает в 10-20 раз

   zzerro

11 — 25.01.11 — 17:39

(7) Мне оформление не нужно, ничего такого не делаю, просто присваиваю значения ячейкам.
(9) Отключал, никакой разницы ощутимой не заметил

Вот собственно код:

Эксель = Новый COMОбъект(«Excel.Application»);
// Запретим экселю выдавать всякие предупреждения
Эксель.DisplayAlerts = False;

    // Для ускорения вывода информации в Excel можно отключить обновление экрана.
Эксель.ScreenUpdating = 0;
Эксель.EnableEvents = 0;
Эксель.Visible = 0;

Книга = Эксель.WorkBooks.Add();
Лист = Книга.WorkSheets(1);

// Рез — это таблица значений, которую нужно сохранить в эксель
КолЗап = Рез.Количество();
НомерСтроки = 1;
Для каждого Стр из Рез Цикл
   ПроцентВыполнения = Цел(НомерСтроки/КолЗап*100);
   Если ПроцентВыполнения % 5 = 0 Тогда
       // Обновляем состояние каждые 5 % элементов
       Состояние(«Построение отчета: » + ПроцентВыполнения + » %»);
   КонецЕсли;
   НомерСтроки = НомерСтроки + 1;
   Лист.Cells(НомерСтроки, 1).Value = Стр.Орг;  
   // Дата, номер, сумма счета
   Лист.Cells(НомерСтроки, 2).Value = Формат(Стр.Счет_Дата,»ДФ=dd.MM.yyyy»);
   Лист.Cells(НомерСтроки, 3).Value = Формат(Стр.Счет_Номер,»ЧГ=0″);
   Лист.Cells(НомерСтроки, 4).Value = Стр.Счет_Сумма;
// и так далее еще 15 колонок

   zzerro

12 — 25.01.11 — 17:40

80 тыс записей выводит минут 30 а то и больше… многовато

   Happy Bear

13 — 25.01.11 — 17:41

(11) через ADO скорость увеличивается существенно, сам проверял

   zzerro

14 — 25.01.11 — 17:41

(1) А можно пример?

   simol

15 — 25.01.11 — 17:42

В DBF, а его открыть в Excel?

   zzerro

16 — 25.01.11 — 17:42

(13) Можно пример, а то считывание через ADO делал, а вот с записью не сталкивался еще

   zzerro

17 — 25.01.11 — 17:43

(15) DBF не подойдет… уж лучше тогда csv

   КМ155

18 — 25.01.11 — 17:47

(16) тот же рекордсет
+ AddNew

   izekia

19 — 25.01.11 — 17:54

(14) попробую накидать, ты, кстати, зачем дату форматируешь?

   izekia

20 — 25.01.11 — 17:55

кстати, еще есть вариант напрямую в эксель тащить с сиквела, но здесь проблема с безопасностью, как я понимаю

   Happy Bear

21 — 25.01.11 — 17:57

(16)

СтрокаПодключения = «Provider=Microsoft.Jet.OLEDB.4.0; Data Source = » + ИмяФайлаЗагрузки;
СтрокаПодключения = СтрокаПодключения + «; Extended Properties = «+»»»Excel 8.0″+»;HDR=NO;IMEX=0″»;»;

Command = Новый COMОбъект(«ADODB.Command»);
axCatalog = Новый COMОбъект(«ADOX.Catalog»);                                           axCatalog.ActiveConnection = Connection;
ИмяТаблицы = axCatalog.Tables(0).Name;
RecordSet = Новый COMОбъект(«ADODB.RecordSet»);
Command.ActiveConnection = Connection;
Command.CommandText = «CREATE TABLE Выгрузка (N float, Артикул char(50), Наименование char(255), Количество float, СтавкаНДС char(25), Цена float, СуммаНДС float, СуммаСНДС float, ГодКампании float, СимволКампании float, ВидТовара float)»;
Command.CommandType = 1;
RecordSet = Command.Execute();

           Command.CommandText = «INSERT INTO Выгрузка VALUES (» + Формат(ВыборкаПоСтрокам.НомерСтроки, СтрокаФормата) + «, ‘» + Артикул + «‘, ‘» + Наименование + «‘, » + Формат(ВыборкаПоСтрокам.Количество, СтрокаФормата) + «, ‘» + ВыборкаПоСтрокам.СтавкаНДС + «‘, » + Формат(ВыборкаПоСтрокам.Цена, СтрокаФормата) + «, » + Формат(ВыборкаПоСтрокам.СуммаНДС, СтрокаФормата) + «, » + Формат(ВыборкаПоСтрокам.СуммаСНДС, СтрокаФормата) + «, » + Формат(ВыборкаПоСтрокам.ГодКампании, СтрокаФормата) + «, » + Формат(ВыборкаПоСтрокам.СимволКампании, СтрокаФормата) + «, » + Формат(ВыборкаПоСтрокам.ВидТовара, СтрокаФормата) + «)»;
Command.CommandType = 1;
RecordSet = Command.Execute();

   Tatitutu

22 — 25.01.11 — 17:59

сохрани таблицу как копию в формате htm
а потом открой в ексели и сохрани как нужно
в разы скорость изменится.

   izekia

23 — 25.01.11 — 18:06

   izekia

24 — 25.01.11 — 18:12

просто дома все ссылки

   ado

25 — 25.01.11 — 18:13

(0) А как насчет Йокселя? Или он с новыми форматами офиса не дружит?

   AversDik2

26 — 25.01.11 — 18:13

(0) Выгрузить в SQL (отдельную базу) и из нее взять данные в Excel

   ado

27 — 25.01.11 — 18:15

(26) По идее, не быстрее ADO будет.

   asady

28 — 26.01.11 — 08:56

  

izekia

29 — 26.01.11 — 15:50

через COMSafeArray конечно быстрее
вот простой пример с использованием XML и XSL:
   тз = Новый ТаблицаЗначений;
   тз.Колонки.Добавить(«Число», Новый ОписаниеТипов(«Число»), «Число», 10);
   тз.Колонки.Добавить(«Строка», Новый ОписаниеТипов(«Строка»), «Строка», 30);
   тз.Колонки.Добавить(«Дата», Новый ОписаниеТипов(«Дата»), «Дата», 10);
   Для инд = 1 По 10 Цикл
       стр = тз.Добавить();
       стр.Число = инд;
       стр.Строка = «Строка»;
       стр.Дата = ТекущаяДата();
   КонецЦикла;
   записьXML = Новый ЗаписьXML;
   записьXML.УстановитьСтроку(«windows-1251»);
   записьXML.ЗаписатьОбъявлениеXML();
   записьXML.ЗаписатьНачалоЭлемента(«ТаблицаЗначений»);
   записьXML.ЗаписатьНачалоЭлемента(«Колонки»);
   Для Каждого колонка из тз.Колонки Цикл
       записьXML.ЗаписатьНачалоЭлемента(«Колонка»);
       записьXML.ЗаписатьАтрибут(«Заголовок», колонка.Заголовок);
       записьXML.ЗаписатьАтрибут(«Ширина», Строка(колонка.Ширина));
       записьXML.ЗаписатьКонецЭлемента();
   КонецЦикла;
   записьXML.ЗаписатьКонецЭлемента();
   Для Каждого строка из тз Цикл
       записьXML.ЗаписатьНачалоЭлемента(«Строка»);
       Для Каждого колонка из тз.Колонки Цикл
           записьXML.ЗаписатьНачалоЭлемента(колонка.Имя);
           записьXML.ЗаписатьТекст(XMLСтрока(строка[колонка.Имя]));
           записьXML.ЗаписатьКонецЭлемента();
       КонецЦикла;
       записьXML.ЗаписатьКонецЭлемента();
   КонецЦикла;
   записьXML.ЗаписатьКонецЭлемента();
   хсл = Новый ПреобразованиеXSL;
   хсл.ЗагрузитьИзСтроки(  «<xsl:stylesheet version=»»1.0″» xmlns:xsl=»»http://www.w3.org/1999/XSL/Transform»» xmlns:ss=»»urn:schemas-microsoft-com:office:spreadsheet»»>
                           |
                           |    <xsl:template match=»»/»»>
                           |        <ss:Workbook>
                           |            <ss:Styles>
                           |                <ss:Style ss:ID=»»1″»>
                           |                    <ss:Font ss:Bold=»»1″»/>
                           |                </ss:Style>
                           |            </ss:Styles>
                           |            <ss:Worksheet ss:Name=»»Test»»>
                           |                <ss:Table>
                           |                    <xsl:apply-templates />
                           |                </ss:Table>
                           |            </ss:Worksheet>
                           |        </ss:Workbook>
                           |    </xsl:template>
                           |
                           |    <xsl:template match=»»ТаблицаЗначений/Колонки»»>
                           |        <ss:Row ss:StyleID=»»1″»>
                           |            <xsl:for-each select=»»Колонка»»>
                           |                <ss:Cell>
                           |                    <ss:Data ss:Type=»»String»»><xsl:value-of select=»»@Заголовок»»/></ss:Data>
                           |                </ss:Cell>
                           |            </xsl:for-each>
                           |        </ss:Row>
                           |        <xsl:apply-templates />
                           |    </xsl:template>
                           |
                           |    <xsl:template match=»»ТаблицаЗначений/Строка»»>
                           |        <ss:Row>
                           |            <xsl:for-each select=»»*»»>
                           |                <ss:Cell>
                           |                    <ss:Data ss:Type=»»String»»>
                           |                        <xsl:value-of select=»».»» />
                           |                    </ss:Data>
                           |                </ss:Cell>
                           |            </xsl:for-each>
                           |        </ss:Row>
                           |    </xsl:template>
                           |
                           |</xsl:stylesheet>»);
   результат = Новый ЗаписьXML;
   результат.ОткрытьФайл(«c:worktemptest.xls»);
   хсл.ПреобразоватьИзСтроки(записьXML.Закрыть(), результат);
   результат.Закрыть();

I have the following routine that dumps a DataTable into an Excel worksheet.

    private void RenderDataTableOnXlSheet(DataTable dt, Excel.Worksheet xlWk, 
                                    string [] columnNames, string [] fieldNames)
    {
        // render the column names (e.g. headers)
        for (int i = 0; i < columnNames.Length; i++)
            xlWk.Cells[1, i + 1] = columnNames[i];

        // render the data 
        for (int i = 0; i < fieldNames.Length; i++)
        {
            for (int j = 0; j < dt.Rows.Count; j++)
            {
                xlWk.Cells[j + 2, i + 1] = dt.Rows[j][fieldNames[i]].ToString();
            }
        }
    }

For whatever reason, dumping DataTable of 25 columns and 400 rows takes about 10-15 seconds on my relatively modern PC. Takes even longer testers’ machines.

Is there anything I can do to speed up this code? Or is interop just inherently slow?

SOLUTION: Based on suggestions from Helen Toomik, I’ve modified the method and it should now work for several common data types (int32, double, datetime, string). Feel free to extend it. The speed for processing my dataset went from 15 seconds to under 1.

    private void RenderDataTableOnXlSheet(DataTable dt, Excel.Worksheet xlWk, string [] columnNames, string [] fieldNames)
    {
        Excel.Range rngExcel = null;
        Excel.Range headerRange = null;

        try
        {
            // render the column names (e.g. headers)
            for (int i = 0; i < columnNames.Length; i++)
                xlWk.Cells[1, i + 1] = columnNames[i];

            // for each column, create an array and set the array 
            // to the excel range for that column.
            for (int i = 0; i < fieldNames.Length; i++)
            {
                string[,] clnDataString = new string[dt.Rows.Count, 1];
                int[,] clnDataInt = new int[dt.Rows.Count, 1];
                double[,] clnDataDouble = new double[dt.Rows.Count, 1];

                string columnLetter = char.ConvertFromUtf32("A".ToCharArray()[0] + i);
                rngExcel = xlWk.get_Range(columnLetter + "2", Missing.Value);
                rngExcel = rngExcel.get_Resize(dt.Rows.Count, 1);

                string dataTypeName = dt.Columns[fieldNames[i]].DataType.Name;

                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    if (fieldNames[i].Length > 0)
                    {
                        switch (dataTypeName)
                        {
                            case "Int32":
                                clnDataInt[j, 0] = Convert.ToInt32(dt.Rows[j][fieldNames[i]]);
                                break;
                            case "Double":
                                clnDataDouble[j, 0] = Convert.ToDouble(dt.Rows[j][fieldNames[i]]);
                                break;
                            case "DateTime":
                                if (fieldNames[i].ToLower().Contains("time"))
                                    clnDataString[j, 0] = Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToShortTimeString();
                                else if (fieldNames[i].ToLower().Contains("date"))
                                    clnDataString[j, 0] = Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToShortDateString();
                                else 
                                    clnDataString[j, 0] = Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToString();

                                break;
                            default:
                                clnDataString[j, 0] = dt.Rows[j][fieldNames[i]].ToString();
                                break;
                        }
                    }
                    else
                        clnDataString[j, 0] = string.Empty;
                }

                // set values in the sheet wholesale.
                if (dataTypeName == "Int32") 
                    rngExcel.set_Value(Missing.Value, clnDataInt);
                else if (dataTypeName == "Double")
                    rngExcel.set_Value(Missing.Value, clnDataDouble);                             
                else
                    rngExcel.set_Value(Missing.Value, clnDataString);
            }


            // figure out the letter of the last column (supports 1 letter column names)
            string lastColumn = char.ConvertFromUtf32("A".ToCharArray()[0] + columnNames.Length - 1);

            // make the header range bold
            headerRange = xlWk.get_Range("A1", lastColumn + "1");
            headerRange.Font.Bold = true;

            // autofit for better view
            xlWk.Columns.AutoFit();

        }
        finally
        {
            ReleaseObject(headerRange);
            ReleaseObject(rngExcel);
        }
    }

    private void ReleaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch
        {
            obj = null;
        }
        finally
        {
            GC.Collect();
        }
    }

Многие сталкиваются с необходимостью передачи (экспорта) данных из своих программы в Excel.
Ниже мы рассмотрим два варианта для записи данных в Excel файл.
Первый вставка значений в каждую ячейку из кода программы, путем простого перебора (и да… оказывается так многие делают и сейчас)
Второй вариант это заполнение двумерного массива необходимыми значениями и последующая вставка этого массива целиком, так сказать разом.
Ниже представлен маленький тест демонстрирующий разницу в скорости работы двух методов вставки:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;</code>

namespace ExcelTestNet
{
class Program
{
static void Main(string[] args)
{
Excel.Application xlApp;
//Рабочая книга
Excel.Workbook xlWorkbook;
//Лист
Excel._Worksheet xlWorksheet;
//Диапазон
Excel.Range xlRange;

//Создаем Excel
xlApp = new Excel.Application();
//Создали книгу
xlWorkbook = xlApp.Workbooks.Add();
//Добавили новый лист
xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];

//Создали и запустили таймер
Stopwatch watch = new Stopwatch();
watch.Start();

for (int row = 1; row &lt; 100; row++)
for (int col = 1; col &lt; 100; col++)
((Excel.Range)xlWorksheet.Cells[row, col]).Value2 = "row:" + Convert.ToString(row) + ", col:" + Convert.ToString(col);

//Остановили таймер
watch.Stop();
Console.WriteLine("Потрачено времени {0}", watch.Elapsed);

//Создали новый лист
xlWorkbook.Sheets.Add();
xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];

//Перезапустили таймер
watch.Restart();

//Создаем двумерный массив типа string[,] и заполняем его
string[,] data = new string[99, 99];
for (int row = 1; row &lt; 100; row++)
for (int col = 1; col &lt; 100; col++)
data[row-1,col-1]= "row:" + Convert.ToString(row) + ", col:" + Convert.ToString(col);

//Определяем верхнюю левую ячейку для вставки нашего массива
Excel.Range c1 = xlWorksheet.Cells[1, 1];
//Определяем нижнюю правую ячейку для вставки
Excel.Range c2 = xlWorksheet.Cells[data.GetLength(0), data.GetLength(1)]; //Получаем размеры наешго массива

//Создаем диапазон с верхней левой ячейки до нижней правой
xlRange = xlWorksheet.get_Range(c1, c2);
//Записываем в диапазон xlRange содержимое массива data
xlRange.Value = data;

watch.Stop();

Console.WriteLine("Потрачено времени {0}", watch.Elapsed);
Console.ReadLine();

//СОхраняем файл Exel
xlWorkbook.SaveAs("g:\test.xlsx");

//Прибираемся
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
xlWorkbook.Close();
Marshal.ReleaseComObject(xlWorkbook);
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);

}
}

}

Результаты теста:
1. Простая вставка в каждую ячейку 99 строк, 99 столбцов — Потрачено времени 00:00:54.324226
2. Вставка массива 99 строк, 99 столбцов — Потрачено времени 00:00:00.0787437

Вполне ожидаемые результаты.

Но есть одно но, всё это достаточно быстро до того момента, пока не потребуется менять стили (шрифт, цвет шрифта, цвет фона и т.д.), тут уже тормозов не избежать. Пример из практики: выгрузка из 30К записей, вставка массивом по способу выше заняла несколько секунд, возникла необходимость стилизации выгружаемых данных, строки групп одним цветом, вложенные подстроки другим шрифтом, после решения в лоб, выгрузка длилась около 8 часов (там множество условий подсветки).

Естественно, что такой способ выгрузки уже не подходит. Лучшее решение для ускорения выгрузки это писать напрямую в экселевский файл. В моём случае я использовал библиотеку EPPlus. С тем же самым решением в лоб, выгрузка занимает 1 минуту

В связи со спецификой деятельности мне часто приходится создавать приложения для построения отчетов из баз данных. Как правило, использую DBGrid, а результат выгружаю в Excel для дальнейшей аналитики.
Как поступаю: создаю экземпляр Excel-я, изпользую VBA для того, чтобы пробежаться по рабочему листу, вставить данные в ячейки. Соответственно в приложении — работаю с полученным набором данных (ADO), который отображаю для пользователей в гриде.
Что не устраивает? Часто случается так, что запрос возвращает несколько тысяч строк и описанная методика выгрузки в Excel оказывается не очень эффективной: долго.
Довелось увидеть софт, написанный с компонентами DevExpress (это был Quantum Grid, если не ошибаюсь). Там реализована функция выгрузки в Excel. Так вот работает это в разы быстрее.
Собственно вопросы: а как это сделано? Как добиться схожего результата? Правильно ли я понимаю, что выгрузка осуществляется не через COM-сервер (потому и так быстро)?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Private Sub Выгрузка_Click()
    Set bookex = CreateObject("Excel.application") 
    bookex.Workbooks.Add ("")
    bookex.Windows(1).Caption = "Price"
    bookex.Visible = True
    bookex.Range("A1:H1").Value = Array("Заказчик", "Регион", "Город", "Группа услуги", "Наименование услуги", "Цена", "Валюта", "Комментарии")
    Dim dts As Object
        Set dts = Me("[Подчиненная форма ФильтрПоиск]").Form.RecordsetClone 
     Dim i&: i = 2
     dts.MoveFirst
       Do While Not dts.EOF 
        bookex.cells(i, 1) = dts("Заказчик")
        bookex.cells(i, 2) = dts("Регион")
        bookex.cells(i, 3) = dts("Город")
        bookex.cells(i, 4) = dts("Группа услуги")
        bookex.cells(i, 5) = dts("Наименование услуги")
        bookex.cells(i, 6) = dts("Цена")
        bookex.cells(i, 7) = dts("Валюта")
        bookex.cells(i, 8) = dts("Комментарии")
        bookex.cells(1, 1).EntireColumn.AutoFit
        bookex.cells(1, 2).EntireColumn.AutoFit
        bookex.cells(1, 3).EntireColumn.AutoFit
        bookex.cells(1, 4).EntireColumn.AutoFit
        bookex.cells(1, 5).EntireColumn.AutoFit
        bookex.cells(1, 6).EntireColumn.AutoFit
        bookex.cells(1, 7).EntireColumn.AutoFit
        bookex.cells(1, 8).EntireColumn.AutoFit
        i = i + 1
        dts.MoveNext
     Loop
        With bookex.activeworkbook.sheets("Лист1").Select
        bookex.Range("A1:H1").Select
        With bookex.Selection
            .HorizontalAlignment = -4108
            .VerticalAlignment = -4108
            .Font.Name = "Calibri"
            .Font.Bold = True
            .Interior.Color = RGB(197, 217, 241)
    End With
End With
    Set bookex = Nothing
End Sub

Старый
30.05.2011, 19:36

 

#1
 

Участник

Очень медленно происходит выгрузка отчетов в Excel


При выгрузке отчетов в Excel (например стандартный ИНВ-3) выгрузка происходит очень медленно — 80 строк выгружаются 3-5 минут, 4000 строк — несколько часов.

И так в принципе со всеми отчетами, которые используют ComExcelDocument_RU. Из трассировки видно что подвисания начинаются на строке
comRange = comApplication.range(bookMark);
в методе findRange.

MS Office стоит 2010 Standard, пробовал ставить 2007 — не помогло.
Версия аксапты 2009 SP1 RollUp 2.

Может кто сталкивался с таким или хотя бы есть идеи, как побороть? Буду очень признателен.

Старый
30.05.2011, 19:59

 

#2
 

Участник

 

Регистрация: 16.09.2004

Адрес: Москва

Есть альтернативные способы работы с Excel:

1. В шаблон отчета поместить макрос, который будет грузить данные из текстового файла и «ложить» по ячейкам — работает раз в 50 быстрее ComExcelDocument_RU.

2. Работать с excel через ADO — еще быстрее чем вариант 1

Старый
30.05.2011, 20:57

 

#3
 

Участник

В принципе, сейчас в некоторых случаях используем как раз вариант 1. Но переделывать все старые отчеты под такую схему — не айс. Ввиду того, что когда-то это все работало нормально, возникает вопрос, что же все-таки могло измениться (когда-то — это в других конторах, в которых использовался тот же функционал. При этом железо в целом похожее).

Старый
30.05.2011, 21:50

 

#4
 

Участник

Аватар для ice

Лучший по профессии 2014

Цитата:

Сообщение от Leopold Stotch
Посмотреть сообщение

В принципе, сейчас в некоторых случаях используем как раз вариант 1. Но переделывать все старые отчеты под такую схему — не айс. Ввиду того, что когда-то это все работало нормально, возникает вопрос, что же все-таки могло измениться (когда-то — это в других конторах, в которых использовался тот же функционал. При этом железо в целом похожее).

ComExcelDocument_RU, по крайней мере с версии 3.0, всегда работал медленно

Старый
31.05.2011, 03:29

 

#5
 

Участник

Используем Ax4 sp2, вывод отчета происходит путем формирования большой текстовой строки на все строки-столбцы отчета + копирование через буфер. Сами отчеты были оптимизированы, основное время уходило на отработку запроса к БД и проверку всяких условий.

Поставили несколько машин с Win7 + Office 2010 у клиента — некоторые из них стали работать раз в 5-6 медленнее, чем связка Win XP + Office 2007/2003 при формировании отчетов. Причем путем замера времени вызовов в ComExcelDocument_RU было выяснено, что все (!) обращения к объекту Excel выполняются раз в 5-10 медленнее Причина так и не была найдена… Причем на некоторых машинах работает «по-старому» быстро

Старый
31.05.2011, 12:46

 

#8
 

Участник

КОРУС Консалтинг

 

Регистрация: 13.01.2004

Записей в блоге: 3

Поячеечное заполнение (в смысле, отдельной командой заполнять каждую ячейку) всегда будет работать относительно медленно. Общая стратегия ускорения вывода — это команды групповой вставки значений. Заполнение многих ячеек одной командой. В идеале, заполнение сразу всех ячеек одной командой. Как правило, это реализуется одним из следующих способов

1. Буфер обмена
2. RecordSet
3. Выгрузка в промежуточные файлы
4. Запрос из макроса Excel напрямую к внешним данным

Если же у Вас «работало быстро», а потом вдруг стало «работать медленно» при этом сам код не менялся и объем выгружаемых данных остался примерно тем же, то надо смотреть настройки Excel, а также настройки операционной системы. Может, антивирус криво настроен. Может с правами доступа что-то намудрили.

И еще, надеюсь, Вы используете предварительно сформированные шаблоны Excel. Т.е. файлы XLT. Создание отчетов «с нуля» или использование в качестве шаблонов обычных файлов XLS, также существенно замедляет формирование отчетов.

За это сообщение автора поблагодарили: Leopold Stotch (1).

Старый
31.05.2011, 13:47

 

#9
 

Участник

Цитата:

Сообщение от Владимир Максимов
Посмотреть сообщение

Если же у Вас «работало быстро», а потом вдруг стало «работать медленно» при этом сам код не менялся и объем выгружаемых данных остался примерно тем же, то надо смотреть настройки Excel, а также настройки операционной системы. Может, антивирус криво настроен. Может с правами доступа что-то намудрили.

И еще, надеюсь, Вы используете предварительно сформированные шаблоны Excel. Т.е. файлы XLT. Создание отчетов «с нуля» или использование в качестве шаблонов обычных файлов XLS, также существенно замедляет формирование отчетов.

Да, отчеты из шаблонов формируются — самый простой вариант.
В итоге покопались в настройках Excel — для листов на которые происходит выгрузка, в случае, если установлен режим просмотра страницы «Разметка страницы» или «Страничный», то выгрузка идет намного медленнее, если же поставить значение «Обычный», то время выгрузки существенно уменьшается.

За это сообщение автора поблагодарили: coolibin (1).

Показывать по
10
20
40
сообщений

Новая тема

Ответить

maestro_voln

Дата регистрации: 04.03.2009
Сообщений: 289

Есть книга ексель размер 2.5 мб в ней 5 листов при выгрузке в нее справочника номенклатура времени уходит пару часов<br>а если создаю новую книгу и выгружаю в нее то занимает 20-25 мин.<br>в чем проблема тормозов? в размере файла или в количиствах листов или может еще в чем то?

zak555 (398843952)

Дата регистрации: 27.03.2008
Сообщений: 4656

maestro_voln

Дата регистрации: 04.03.2009
Сообщений: 289

«ExcelApp = СоздатьОбъект(«Excel.Application»); <br>РабочаяКнига=ExcelApp.WorkBooks(«Прайс лист.xls»); <br>Страница=РабочаяКнига.Worksheets(«Лист1»); <br>ExcelApp.Visible=0; <br>ExcelApp.ScreenUpdating = 0;<br>ExcelApp.EnableEvents = 0;<br><br>ExcelApp = СоздатьОбъект(«Excel.Application»); <br>НовыеРабочиеКниги=ExcelApp.WorkBooks; <br>РабочаяКнига =НовыеРабочиеКниги.Add();<br>Страница=РабочаяКнига.Worksheets(1); <br>Страница.Name = «Прайс»; <br>ExcelApp.Visible=0; <br>ExcelApp.ScreenUpdating = 0;<br>ExcelApp.EnableEvents = 0;<br>»

Maxim_B

Дата регистрации: 15.01.2009
Сообщений: 29

Посмотрите здесь http://infostart.ru/projects/4225/<br>Там была длинная ветка где обсуждался способ наибыстрейшей работы с большими файлами excel’я

Показывать по
10
20
40
сообщений

Like this post? Please share to your friends:
  • Уроки по изучению word
  • Уроки работы в excel урок 1
  • Ускорение свободного падения excel
  • Уроки по документах word
  • Уроки работы office word