Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Thread + Сервер автоматизации Excel 
:(
    Опции темы
vikaz
Дата 4.12.2009, 07:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



Всем добрый день! Есть сл. код:

CPP файл
Код


#include <vcl.h>
#pragma hdrstop

#include "TExcelThread.h"
#include "Import_Unit.h"
#include "Main_Unit.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TExcelThread::TExcelThread(bool CreateSuspended, AnsiString FileName)
    : TThread(CreateSuspended)
{
 _FileName = FileName;
 i = j =0;
 ShowMessage (FileName);
 OnTerminate = Delete_ExcelThread;
 //------------------------- Excel ----------------------------------
 try
 {
  ExcelApplication1 = Variant::CreateObject("Excel.Application");
 }
 catch (...)
   {
     Import_Form->AddLogLine("Не возможно запустить сервер автоматизации Excel", clRed);
   }

 Import_Form->AddLogLine("Cервер автоматизации Excel запущен", clGreen);

 ExcelApplication1.OlePropertySet("DisplayAlerts", false);
 ExcelApplication1.OlePropertySet("Visible", false);




 Variant Book = ExcelApplication1.OlePropertyGet ("Workbooks").OleFunction("Open", WideString (_FileName));
 Variant SelectCells = ExcelApplication1.OlePropertyGet("Range", WideString ("A5")).OlePropertyGet ("End",0xFFFFEFE7).OlePropertyGet ("End",0xFFFFEFBF);
 SelectCells.OlePropertySet("Name", WideString ("DataBase"));
 i = ((int) (SelectCells.OlePropertyGet("Column")));
 j = ((int) (SelectCells.OlePropertyGet("Row")));

 Import_Form->AddLogLine("Открытие файла:" + _FileName, clBlue);
 Import_Form->AddLogLine("Количество строк:" + IntToStr (j-4), clBlue);
 Import_Form->AddLogLine("Количество столбцов: " + IntToStr (i), clBlue);
 Import_Form->AddLogLine("Начало передачи данных из Excel в локальную БД!!!", clGreen);

 Import_Form->Gauge->MaxValue = j-5;

//------------------------- Local_BD ----------------------------------
 Import_Form->AddLogLine("Создание соединений с локальной БД", clBlack);
 UniQuery_Temporary = new TUniQuery (Application);  // для временной таблицы
 UniQuery_Temporary->Connection = Main_Form->UniConnection1;

 UniQuery_Employee = new TUniQuery (Application);   // для основной таблицы
 UniQuery_Employee->Connection = Main_Form->UniConnection1;

 UniSQL = new TUniSQL (Application);
 UniSQL->Connection = Main_Form->UniConnection1;

 CreateTemporaryTable();
//------------------------- Run Thread ----------------------------------
 inc = 0;

 Resume();


}
//---------------------------------------------------------------------------
void __fastcall TExcelThread::Execute()
{

for (int j1=5; j1 <= j; j1++)
 {
 for (int i1 = 2; i1 <= i; i1++)
 {
  switch (i1)
  {
   case 2: {FIO = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 3: {OrganicNumber = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 4: {Post = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 5: {DateOfBirth = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 6: {NameplateDate = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 7: {RegistrationAddress = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 8: {ResidingAddress = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case    9: {Phone = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
  }
 }
 inc = j1;
 Synchronize(pb);

 WriteExcelToBD ("Insert into temp (FIO, OrganicNumber, Post, DateOfBirth, NameplateDate, RegistrationAddress, ResidingAddress, Phone) values ('"+
 FIO +"','" + OrganicNumber +"','" + Post + "','" + FormatDateTime("yyyy-mm-dd", StrToDate (DateOfBirth)) + "','" + NameplateDate + "','" + RegistrationAddress + "','" + ResidingAddress + "','" + Phone + "')");

 }
}
//---------------------------------------------------------------------------
void __fastcall TExcelThread::pb ()
{
  Import_Form->Gauge->Progress = inc;
}
//---------------------------------------------------------------------------
void __fastcall TExcelThread::Delete_ExcelThread(TObject* Sender)
{
 //------------------------- Local_BD ----------------------------------
 Import_Form->AddLogLine("Отключение от локальной БД", clBlack);
 UniQuery_Temporary->Close();
 UniQuery_Employee->Close();

 delete UniQuery_Temporary;
 delete UniQuery_Employee;
 delete UniSQL;

 //------------------------- Excel ----------------------------------
 try
 {
  ExcelApplication1.OleProcedure ("Quit");
  Import_Form->AddLogLine("Cервер автоматизации Excel успешно закрыт", clGreen);
  ExcelApplication1 = Unassigned;
 }
 catch (...)
            {
             Import_Form->AddLogLine("Ошибка закрытия сервера автоматизации Excel", clRed);
            }
}
//---------------------------------------------------------------------------
void __fastcall TExcelThread::CreateTemporaryTable ()
{
 Import_Form->AddLogLine("Создание временной таблицы", clBlack);
  //UniSQL1->SQL->Add("CREATE TEMPORARY TABLE tmp (");
 UniSQL->SQL->Add("CREATE TABLE IF NOT EXISTS temp (");
 UniSQL->SQL->Add("[OrganicNumber] INTEGER PRIMARY KEY,");
 UniSQL->SQL->Add("[FIO] CHAR(100),");
 UniSQL->SQL->Add("[Post] CHAR(50),");
 UniSQL->SQL->Add("[DateOfBirth] DATE,");
 UniSQL->SQL->Add("[NameplateDate] CHAR(500),");
 UniSQL->SQL->Add("[RegistrationAddress] CHAR(500),");
 UniSQL->SQL->Add("[ResidingAddress] CHAR(500),");
 UniSQL->SQL->Add("[Phone] CHAR(25))");
 UniSQL->Execute();
}
//---------------------------------------------------------------------------
bool __fastcall TExcelThread::WriteExcelToBD (AnsiString Buf)
{
 UniSQL->SQL->Text = Buf;
 try
 {
  UniSQL->Execute();
  return true;
 }
  catch (...)
             {
              Import_Form->AddLogLine("Ошибка записи данных в локальную БД", clRed);
              return false;
             }
}
//---------------------------------------------------------------------------


h файл
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#include "Uni.hpp"
#ifndef TExcelThreadH
#define TExcelThreadH
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class TExcelThread : public TThread
{
private:
    AnsiString _FileName;
    Variant ExcelApplication1;

    TUniQuery * UniQuery_Temporary;  // для временной таблицы
    TUniQuery * UniQuery_Employee;   // для основной таблицы
    TUniSQL *   UniSQL;
        AnsiString FIO, OrganicNumber, Post, DateOfBirth, NameplateDate, RegistrationAddress, ResidingAddress, Phone;
    int inc, i, j;

protected:
    void __fastcall Execute();
    void __fastcall pb ();


public:
    __fastcall TExcelThread(bool CreateSuspended, AnsiString FileName);
    void __fastcall Delete_ExcelThread(TObject* Sender);
    void __fastcall CreateTemporaryTable ();
    bool __fastcall WriteExcelToBD (AnsiString Buf);
};
//---------------------------------------------------------------------------

#endif


Проблема в том, что когда запускается основной поток, появляется сл. ошибка:
user posted image

Такое ощущение, что поток не видит, все что было связанно с инициализацией переменной ExcelApplication. Подскажите, как можно решить проблему...... Заранее спасибо!
ЗЫ. Без потоков все работает нормально, но естественно, виснет форма, от чего и пытаюсь избавиться......
ЗЫ. ЗЫ. Проверил, действительно проблема возникает только в Execute (); 
             проверил так: создал новую функцию, в нее положил только строчку:
             
Код

              FIO = ExcelApplication1.OlePropertyGet("Cells",5,2). OlePropertyGet ("Value");
             
 ,
вызов функции расположил до Resume ();. Все отработалось нормально без ошибки вернув мне значение данной ячейки! ЗАСАДА! :(


Это сообщение отредактировал(а) vikaz - 4.12.2009, 08:01


--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.12.2009, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



vikaz, код работы с COM попробуй заключить между
Код

 CoInitialize(NULL);
//код
CoUninitialize();

PM MAIL   Вверх
vikaz
Дата 4.12.2009, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



user posted image

Код

void __fastcall TExcelThread::Execute()
{


for (int j1=5; j1 <= j; j1++)
 {
 for (int i1 = 2; i1 <= i; i1++)
 {
  CoInitialize(NULL);
  switch (i1)
  {
   case 2: {FIO = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 3: {OrganicNumber = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 4: {Post = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 5: {DateOfBirth = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 6: {NameplateDate = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 7: {RegistrationAddress = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case 8: {ResidingAddress = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
   case    9: {Phone = ExcelApplication1.OlePropertyGet("Cells",j1,i1). OlePropertyGet ("Value"); break;}
  }
  CoUninitialize();
 }
 inc = j1;
 Synchronize(pb);
 }
}



--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.12.2009, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



vikaz, вообще то работа с Execel у тебя начинается уже в конструкторе потока.

А в целом - не совсем удачная реализация идеи. Я бы написал отдельный класс для работы с Excel и уже в нем реализовал асинхронный ввод - вывод.
PM MAIL   Вверх
vikaz
Дата 4.12.2009, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



Дык, так и начинал писать! Но потом решил внести в поток и началась попа. А для асинхронного ввода-вывода, как лучше реализовать поток, через этот же класс или взять чисто API?


--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.12.2009, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(vikaz @  4.12.2009,  09:11 Найти цитируемый пост)
А для асинхронного ввода-вывода, как лучше реализовать поток, через этот же класс или взять чисто API?

Да без разницы. TThread обыкновенный враппер под winapi-шный поток, снабженный гламуром. Собственно из-за этого его и целесообразней юзать под Борманом.
PM MAIL   Вверх
vikaz
Дата 4.12.2009, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



Цитата(mrbrooks @  4.12.2009,  11:27 Найти цитируемый пост)
Да без разницы. TThread обыкновенный враппер под winapi-шный поток, снабженный гламуром. Собственно из-за этого его и целесообразней юзать под Борманом. 


Самое поршивое, что я так с самого начала и делал, но возникала та же ошибка! Только поэтому я перенес все в конструктор для проверки, но это тоже не помогло. Я так же просто передавал Variant  в конструктор потока и пытался с ним работать. Но получалось все еще смешнее, ошибки не было, но после первого же обращения к OLE приводило к завершению потока...... :(


--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.12.2009, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



vikaz, кстати попробуй при работе из основного потока - без TThread - в цикле работы использовать Application->ProcessMessages(). Это не очень кошерный подход - но все же.
Цитата(vikaz @  4.12.2009,  09:35 Найти цитируемый пост)
Самое поршивое, что я так с самого начала и делал, но возникала та же ошибка! Только поэтому я перенес все в конструктор для проверки, но это тоже не помогло. Я так же просто передавал Variant  в конструктор потока и пытался с ним работать.

Я думаю что в поток стоит вынести только обработку данных - но не инициализацию самого объекта для работы с Excel. 
PM MAIL   Вверх
vikaz
Дата 4.12.2009, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



Цитата(mrbrooks @  4.12.2009,  11:44 Найти цитируемый пост)
Я думаю что в поток стоит вынести только обработку данных - но не инициализацию самого объекта для работы с Excel.  


Полностью с тобой согласен камрад, но повторюсь, инициализацию внес в  конструктор только для проверки.... smile
Буду пробовать, если не получится, попрошу у Вас помощи! Огромное спасибо....



--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.12.2009, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



vikaz, ок.

Попробуй действовать по такому шаблону:
Код

void Form1::WorkExcel()
{
CoInitialize(NULL);
try
{
   //работа с exel
}
catch(...)
{
  //blablabla
}
finaly
{
   CoUninitialize();
}
}

//Thread
void __fastcall ThreadExcel::Execute()
{
   Form1->WorkExcel();
}
}
 

Это конечно при условие что нет работы в потоке с гуем. 
Хотя все таки кошернее замутить свой класс. Все таки ООП наше все  smile 

Удачи!

Это сообщение отредактировал(а) mrbrooks - 4.12.2009, 10:00
PM MAIL   Вверх
xvr
Дата 4.12.2009, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



  •  Вся работа с COM объектом должна производится в том потоке, где он был создан.
  •  Если в потоке общаются с COM объектами (и создают их), то ВСЕ тело потока должно быть заключено в CoInitialize/CoUninitialize
Собственно это все - все должно работать

PM MAIL   Вверх
vikaz
Дата 4.12.2009, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



Цитата(xvr @  4.12.2009,  15:26 Найти цитируемый пост)
    *  Вся работа с COM объектом должна производится в том потоке, где он был создан.
    *  Если в потоке общаются с COM объектами (и создают их), то ВСЕ тело потока должно быть заключено в CoInitialize/CoUninitialize

Собственно это все - все должно работать


Спасибо, учту это в дальнейшем! smile


--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.12.2009, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(xvr @  4.12.2009,  13:26 Найти цитируемый пост)
Вся работа с COM объектом должна производится в том потоке, где он был создан.

значит мой шаблон будет враждебно настроен к приложению?  smile 
PM MAIL   Вверх
xvr
Дата 4.12.2009, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(mrbrooks @ 4.12.2009,  15:15)
Цитата(xvr @  4.12.2009,  13:26 Найти цитируемый пост)
Вся работа с COM объектом должна производится в том потоке, где он был создан.

значит мой шаблон будет враждебно настроен к приложению?  smile

Нет, не будет. В твоем шаблоне вся работа происходит в отдельном thread'е. И то, что функцию, которая эту работу производит, засунули в чужой класс, дела не меняет  smile 

PM MAIL   Вверх
vikaz
Дата 4.12.2009, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 869
Регистрация: 15.2.2006

Репутация: 10
Всего: 12



Получается, что все, начиная от инициализации до отключения от сервера автоматизации, должно находиться, по сути, в функции Execute?


--------------------
user posted image

Нет ничего настолько исправного, чтобы в нем не было ошибок. /Ф. Петрарка/ 
PM MAIL ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0757 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.