как увеличить производительность приложения???
От: Serjinio  
Дата: 26.06.09 15:07
Оценка:
привет!
имеется некое приложение на VS C#, в котором происходит выборка данных и экспорт их в файл excel, так вот проблема следующая: экспортируется около 70 тыс. строк и занимает это по времени нереально много (около 30 минут, а то и более, смотря на какой машине запустишь). может кто подскажет как видоизменить код для повышения производительности?

foreach (ExcelStudy est in _ExcelStudy)
            {
                //toolStripProgressBar1.Value += 1;
                excelcells = (Excel.Range)excelworksheet.Cells[n, 20];
                excelcells.Value2 = est.Uplan.ToString();
                excelcells = (Excel.Range)excelworksheet.Cells[n, 21];
                excelcells.Value2 = est.CodeGroup;
                excelcells = (Excel.Range)excelworksheet.Cells[n, 22];
                excelcells.Value2 = est.Course;
                excelcells = (Excel.Range)excelworksheet.Cells[n, 23];
                excelcells.Value2 = est.IdDisc;
                n++;
            }

в массиве _ExcelStudy около 70000 объектов
Re: как увеличить производительность приложения???
От: EM Великобритания  
Дата: 26.06.09 15:27
Оценка: 2 (2) +1
Здравствуйте, Serjinio, Вы писали:

S>привет!

S>имеется некое приложение на VS C#, в котором происходит выборка данных и экспорт их в файл excel, так вот проблема следующая: экспортируется около 70 тыс. строк и занимает это по времени нереально много (около 30 минут, а то и более, смотря на какой машине запустишь). может кто подскажет как видоизменить код для повышения производительности?

S>
S>foreach (ExcelStudy est in _ExcelStudy)
S>            {
S>                //toolStripProgressBar1.Value += 1;
S>                excelcells = (Excel.Range)excelworksheet.Cells[n, 20];
S>                excelcells.Value2 = est.Uplan.ToString();
S>                excelcells = (Excel.Range)excelworksheet.Cells[n, 21];
S>                excelcells.Value2 = est.CodeGroup;
S>                excelcells = (Excel.Range)excelworksheet.Cells[n, 22];
S>                excelcells.Value2 = est.Course;
S>                excelcells = (Excel.Range)excelworksheet.Cells[n, 23];
S>                excelcells.Value2 = est.IdDisc;
S>                n++;
S>            }

S>

S>в массиве _ExcelStudy около 70000 объектов

Выкинуть все это тормозное Excel-евское OLE и сгенерить XML в Excel-евском формате?
Опыт — это такая вещь, которая появляется сразу после того, как была нужна...
Re: как увеличить производительность приложения???
От: Ovl Россия  
Дата: 26.06.09 15:29
Оценка:
если форматирования никакого не предполагается, то экспортируйте списоком. что-то вроде:

start = (Excel.Range)excelworksheet.Cells[n, 20];
end = (Excel.Range)excelworksheet.Cells[n, 23];

range = excelworksheet.get_Range(start, end);
range.Value2 = new [] { est.Uplan.ToString(), est.CodeGroup, est.Course, est.IdDisc };
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[2]: как увеличить производительность приложения???
От: Serjinio  
Дата: 26.06.09 16:09
Оценка:
Здравствуйте, Ovl, Вы писали:

Ovl>если форматирования никакого не предполагается, то экспортируйте списоком. что-то вроде:


Ovl>
Ovl>start = (Excel.Range)excelworksheet.Cells[n, 20];
Ovl>end = (Excel.Range)excelworksheet.Cells[n, 23];

Ovl>range = excelworksheet.get_Range(start, end);
Ovl>range.Value2 = new [] { est.Uplan.ToString(), est.CodeGroup, est.Course, est.IdDisc };
Ovl>

так так так...вот тут поподробнее. тобишь вот так?

foreach (ExcelStudy est in _ExcelStudy)
            {
               start = (Excel.Range)excelworksheet.Cells[n, 20];
               end = (Excel.Range)excelworksheet.Cells[n, 23];

               range = excelworksheet.get_Range(start, end);
               range.Value2 = new [] { est.Uplan.ToString(), est.CodeGroup, est.Course, est.IdDisc };
                n++;
            }
Re[3]: как увеличить производительность приложения???
От: Ovl Россия  
Дата: 26.06.09 16:14
Оценка:
S>
S>foreach (ExcelStudy est in _ExcelStudy)
S>            {
S>               start = (Excel.Range)excelworksheet.Cells[n, 20];
S>               end = (Excel.Range)excelworksheet.Cells[n, 23];

S>               range = excelworksheet.get_Range(start, end);
S>               range.Value2 = new [] { est.Uplan.ToString(), est.CodeGroup, est.Course, est.IdDisc };
S>                n++;
S>            }

S>


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

а что — получилось?
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re: как увеличить производительность приложения???
От: hexamino http://hexamino.blogspot.com/
Дата: 26.06.09 16:27
Оценка: +1
Здравствуйте, Serjinio, Вы писали:

S>привет!

S>имеется некое приложение на VS C#, в котором происходит выборка данных и экспорт их в файл excel, так вот проблема следующая: экспортируется около 70 тыс. строк и занимает это по времени нереально много (около 30 минут, а то и более, смотря на какой машине запустишь). может кто подскажет как видоизменить код для повышения производительности?

Я бы писал в текстовый CSV-файл, и потом импортировал его в Excel.
Re: как увеличить производительность приложения???
От: yuriylsh  
Дата: 27.06.09 02:04
Оценка:
Здравствуйте, Serjinio, Вы писали:

S>привет!

S>имеется некое приложение на VS C#, в котором происходит выборка данных и экспорт их в файл excel, так вот проблема следующая: экспортируется около 70 тыс. строк и занимает это по времени нереально много (около 30 минут, а то и более, смотря на какой машине запустишь). может кто подскажет как видоизменить код для повышения производительности?

Мда, 30 минут это что-то не очень шустренько... Про экспорт в csv тебе уже написали, хорошее направление. Можно еще такой вариант, если тебя устроит по производительности (у меня на домашнем компе отрабатывает за 24 секунды):
private static void Main()
{
    // так как ты собираешься вставлять 70000 строк, предполагаю, что работаем с Excel 2007
    const string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Mode=ReadWrite;Extended Properties=\"Excel 12.0 Xml;HDR=YES;\"";
    string path = new FileInfo("test.xlsx").FullName;
    string date = DateTime.Now.ToShortDateString();

    if (File.Exists(path))
        File.Delete(path);

    var connection = new OleDbConnection(string.Format(connectionString, path));
    OleDbCommand cmd = connection.CreateCommand();

    try
    {
        var timer = new Stopwatch();
        timer.Start();

        connection.Open();

        // создадим сам test.xlsx и worksheet с именем MYSHEET :) 
        cmd.CommandText = "CREATE TABLE MYSHEET (col1 int, col2 char(255), col3 date)";
        cmd.ExecuteNonQuery();

        // вставка
        string cmdText = " INSERT INTO [MYSHEET$] (col1, col2, col3) Values ({0}, '{1}', '{2}')";
        for (int i = 0; i < 70000; i++)
        {
            cmd.CommandText = string.Format(cmdText, i + 1, "some string", date);
            cmd.ExecuteNonQuery();
        }

        timer.Stop();
        Console.WriteLine("Elapsed {0} seconds", timer.ElapsedMilliseconds/1000);
    }
    finally
    {
        if (connection.State != ConnectionState.Closed)
            connection.Close();
        connection.Dispose();
    }

    Console.WriteLine("done...");
    Console.ReadKey();
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1228>>
Luck in life always exists in the form of an abstract class that cannot be instantiated directly and needs to be inherited by hard work and dedication.
Re[2]: как увеличить производительность приложения???
От: Serjinio  
Дата: 27.06.09 20:33
Оценка:
Здравствуйте, yuriylsh, Вы писали:



Y>Мда, 30 минут это что-то не очень шустренько... Про экспорт в csv тебе уже написали, хорошее направление. Можно еще такой вариант, если тебя устроит по производительности (у меня на домашнем компе отрабатывает за 24 секунды):

Y>
Y>private static void Main()
Y>{
Y>    // так как ты собираешься вставлять 70000 строк, предполагаю, что работаем с Excel 2007
Y>    const string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Mode=ReadWrite;Extended Properties=\"Excel 12.0 Xml;HDR=YES;\"";
Y>    string path = new FileInfo("test.xlsx").FullName;
Y>    string date = DateTime.Now.ToShortDateString();

Y>    if (File.Exists(path))
Y>        File.Delete(path);

Y>    var connection = new OleDbConnection(string.Format(connectionString, path));
Y>    OleDbCommand cmd = connection.CreateCommand();

Y>    try
Y>    {
Y>        var timer = new Stopwatch();
Y>        timer.Start();

Y>        connection.Open();

Y>        // создадим сам test.xlsx и worksheet с именем MYSHEET :) 
Y>        cmd.CommandText = "CREATE TABLE MYSHEET (col1 int, col2 char(255), col3 date)";
Y>        cmd.ExecuteNonQuery();

Y>        // вставка
Y>        string cmdText = " INSERT INTO [MYSHEET$] (col1, col2, col3) Values ({0}, '{1}', '{2}')";
Y>        for (int i = 0; i < 70000; i++)
Y>        {
Y>            cmd.CommandText = string.Format(cmdText, i + 1, "some string", date);
Y>            cmd.ExecuteNonQuery();
Y>        }

Y>        timer.Stop();
Y>        Console.WriteLine("Elapsed {0} seconds", timer.ElapsedMilliseconds/1000);
Y>    }
Y>    finally
Y>    {
Y>        if (connection.State != ConnectionState.Closed)
Y>            connection.Close();
Y>        connection.Dispose();
Y>    }

Y>    Console.WriteLine("done...");
Y>    Console.ReadKey();
Y>}
Y>

По производительности устраивает вполне, только вот такой вопрос у меня возник: мне необходимо дописывать эти данные в уже существующий файл, причем не в конец, а начиная с первой строки, но в другие колонки. Возможно ли это?
Re[3]: как увеличить производительность приложения???
От: MozgC США http://nightcoder.livejournal.com
Дата: 27.06.09 21:04
Оценка:
Здравствуйте, Serjinio, Вы писали:

S>так так так...вот тут поподробнее. тобишь вот так?


S>
S>foreach (ExcelStudy est in _ExcelStudy)
S>            {
S>               start = (Excel.Range)excelworksheet.Cells[n, 20];
S>               end = (Excel.Range)excelworksheet.Cells[n, 23];

S>               range = excelworksheet.get_Range(start, end);
S>               range.Value2 = new [] { est.Uplan.ToString(), est.CodeGroup, est.Course, est.IdDisc };
S>                n++;
S>            }

S>


Нет не так. Лучше сначала _ExcelStudy перегоните в object[,] а потом за один раз (а не в цикле foreach) присвойте значение выбранному региону ячеек (70000 строк х 4 столбца), т.е. как-то так:

var array = new object[rows, cols];
... // заполняем массив
range = excelworksheet.get_Range((Excel.Range)excelworksheet.Cells[1, 20], (Excel.Range)excelworksheet.Cells[rows + 1, 23]);
range.Value2 = array;
Re[3]: как увеличить производительность приложения???
От: yuriylsh  
Дата: 27.06.09 23:19
Оценка: 1 (1)
Здравствуйте, Serjinio, Вы писали:
S>По производительности устраивает вполне, только вот такой вопрос у меня возник: мне необходимо дописывать эти данные в уже существующий файл, причем не в конец, а начиная с первой строки, но в другие колонки. Возможно ли это?

А, тут INSERT не прокатит, можно похимичить с UPDATE, но гораздо проще (и быстрее, буквально 1 секунда) все же Automation. Например, чтобы добавить 2 колонки с данными файл полученный моим предидущим кодом, можно сделать так:

var data = new string[70000,2];
for (int i = 0; i < 70000; i++)
{
    data[i, 0] = i.ToString();
    data[i, 1] = "I am FAST!!!";
}
range = worksheet.get_Range("D2", System.Reflection.Missing.Value);
range = range.get_Resize(70000, 2);
range.Value2 = data;


Не замерял точно, но на глаз — мгновенно
Luck in life always exists in the form of an abstract class that cannot be instantiated directly and needs to be inherited by hard work and dedication.
Re[4]: как увеличить производительность приложения???
От: yuriylsh  
Дата: 27.06.09 23:26
Оценка:
упс, только ща заметил что MozgC уже показал
Автор: MozgC
Дата: 28.06.09
это решение.
Luck in life always exists in the form of an abstract class that cannot be instantiated directly and needs to be inherited by hard work and dedication.
Re: как увеличить производительность приложения???
От: Lloyd Россия  
Дата: 27.06.09 23:28
Оценка:
Здравствуйте, Serjinio, Вы писали:

S>имеется некое приложение на VS C#, в котором происходит выборка данных и экспорт их в файл excel, так вот проблема следующая: экспортируется около 70 тыс. строк и занимает это по времени нереально много (около 30 минут, а то и более, смотря на какой машине запустишь). может кто подскажет как видоизменить код для повышения производительности?


А если такой вариант попробовать: написать Excel-макрос, который будет парсить переданный ему файл и генерить нужный контент уже изнутри Excel-я. А в программе просто подготовить нужные данные и дернуть макрос.
По идее это может сильно "разогнать" код, т.к. затраты на межпроцессное взаимодействие будут сведены к минимуму.
Re[4]: как увеличить производительность приложения???
От: Serjinio  
Дата: 28.06.09 18:41
Оценка:
Здравствуйте, yuriylsh, Вы писали:

Y>Здравствуйте, Serjinio, Вы писали:

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

Y>А, тут INSERT не прокатит, можно похимичить с UPDATE, но гораздо проще (и быстрее, буквально 1 секунда) все же Automation. Например, чтобы добавить 2 колонки с данными файл полученный моим предидущим кодом, можно сделать так:


Y>
Y>var data = new string[70000,2];
Y>for (int i = 0; i < 70000; i++)
Y>{
Y>    data[i, 0] = i.ToString();
Y>    data[i, 1] = "I am FAST!!!";
Y>}
Y>range = worksheet.get_Range("D2", System.Reflection.Missing.Value);
Y>range = range.get_Resize(70000, 2);
Y>range.Value2 = data;
Y>


Y>Не замерял точно, но на глаз — мгновенно

О! Такой вариант меня устраивает по времени вполне. спасибо за решение проблемы)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.