Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
Builder 6

Сохранение файла Excel, заполненного из не основного потока

12.04.2019, 13:18. Показов 1595. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго всем времени суток, господа.
Помогите решить следующею проблемку.
Данный код, открывает файл Excell только в режиме для чтения. И какие бы манипуляции с таблицей я не проводил бы, после сохранения ничего не сохраняется.

Открытие, редактирование выполняю не из основного потока программы.

Код открытия:
C++
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
int excellFileWriter::InitExcell(String filePath)
{
  //CoInitialize(NULL);
  this->Path = filePath;
  try
  {
     ExcellApp=Variant::GetActiveObject("Excel.Application");
  }
  catch(...)
  {
     try
     {
        ExcellApp=Variant::CreateObject("Excel.Application");
     }
     catch (...)
     {
        return 1; 
     }
  }
 
  try
  {
    if(this->Path.Length()!=0){
      this->Books = ExcellApp.OlePropertyGet("WorkBooks");
      this->Book = this->Books.OlePropertyGet("Open", this->Path.c_str());
    }
    else{
      ExcellApp.OlePropertyGet("WorkBooks").OleProcedure("add");
      this->Books = ExcellApp.OlePropertyGet("WorkBooks");
    }
    Sheet=ExcellApp.OlePropertyGet("WorkSheets",1);
  }
  catch(...)
  {
    return 2; 
  }
}

Сохранение:
C++
1
2
3
4
5
6
7
  try{
    this->Books.OlePropertyGet("Item", 1).OleProcedure("Save");
    return 0;
  }
  catch(...){
    return 1;
  }

Вызов метода открытия:
C++
1
2
3
4
5
6
7
8
9
10
__fastcall ProgressShowClass::ProgressShowClass(bool CreateSuspended)
        : TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall ProgressShowClass::Execute()
{
  Form1->CreateExcelFile();
  this->Terminate();
}
В методе Form1->CreateExcelFile(); и происходит вызов метода открытия, редактирования и сохранения файла. Принадлежит он классу Form1 потому что на этой форме и располагаются визуальные компоненты, информация из которых и заносится в Excel.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.04.2019, 13:18
Ответы с готовыми решениями:

Выполнение слота основного потока через сигнал второстепенного потока
Доброго времени суток! Вопрос следующий. В основном потоке создается кнопка и Qlabel class Ui_QtGuiApp4Class { public: //...

Вызов метода основного потока из второстепенного потока
Здравствуйте! Столкнулся с проблемой: есть два потока (основной и не основной), мне нужно вызвать из не основного потока метод, который...

Сохранение файла на уровне потока
Как из этой функции сохранения файла на уровне операционки сделать функцию сохранения файла на уровне потока? int Save(char* fileName,...

8
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33404 / 21514 / 8236
Регистрация: 22.10.2011
Сообщений: 36,914
Записей в блоге: 12
12.04.2019, 13:21
Тестовый проект (минимальный) можно присоединить? А то у меня хрустальный шар в ремонте, а в приведенном коде вызова Synchronize я не вижу.
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
12.04.2019, 13:47  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Тестовый проект (минимальный) можно присоединить?
Сейчас организуем.

Добавлено через 21 минуту
Цитата Сообщение от volvo Посмотреть сообщение
Тестовый проект (минимальный) можно присоединить?
На удивление, когда я вырвал код из контекста всей программы в отдельный проект, то все сработало как задумывалось.
0
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
12.04.2019, 13:50  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Тестовый проект (минимальный)
Я его все таки выложу, укажите на упущения, может они только в рамках малого проекта не оказывают влияния.

test.rar
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33404 / 21514 / 8236
Регистрация: 22.10.2011
Сообщений: 36,914
Записей в блоге: 12
12.04.2019, 15:38
CoInitialize у тебя вызывается, а CoUninitialize - нет, а ведь:
A thread must call CoUninitialize once for each successful call it has made to the CoInitialize or CoInitializeEx function, including any call that returns S_FALSE
(отсюда)

Ну, а то, что ты работаешь из дополнительного потока с GUI-потоком без синхронизации я уже написал выше. Это к добру не приведет, используй Synchronize(), хотя тогда я не понимаю, зачем тебе нужен дополнительный поток.
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
12.04.2019, 16:40  [ТС]
Спасибо.

Цитата Сообщение от volvo Посмотреть сообщение
хотя тогда я не понимаю, зачем тебе нужен дополнительный поток.
В доп потоке я запускаю метод создания Excel документа, а поток с GUI отображать окно, в котором ProgressBar бегает, тем самым показывая, что мол, работа ведется, подождите. А как только метод создания Excel завершился, второй поток закрывает окно с прогресс баром. Вот такой был план.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33404 / 21514 / 8236
Регистрация: 22.10.2011
Сообщений: 36,914
Записей в блоге: 12
12.04.2019, 17:32
Так вот это очень плохой план. Форма и все визуальные компоненты, которые на ней находится, обязаны работать в контексте основного (GUI) потока (потому что компоненты в VCL НЕ потокобезопасны), и получается, что обновление ProgressBar-а нужно выносить в отдельный метод, и выполнять его через функцию Synchronize дополнительного потока, чтобы потом не было сюрпризов. Точно так же, нужно все действия с формой (показ, обновление, удаление) делать в контексте этого же, основного потока. Вот и получается, что тебе надо через Synchronize() вызывать все содержимое Execute(), а это сводит на нет преимущества дополнительного потока. Мало того, это еще и усложняет работу программы.

Ну, или полностью перерабатывать код, чтобы можно было синхронизировать только те участки, которые работают с визуальными компонентами. А теперь вопрос: оно надо?
0
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
15.04.2019, 07:22  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
А теперь вопрос: оно надо?
А как иначе можно заставить реализовать одновременное заполнения документа Excel и в процессе этого
работу ProgressBar-а?
0
65 / 31 / 18
Регистрация: 16.03.2019
Сообщений: 84
15.04.2019, 11:28
Если нужно синхронизировать только работу прогресс-бара (код я не смотрел),
можно передавать только % выполнения заполнения документа Excell из дополнительного потока в GUI поток. Например через InterlockedExchangeAdd(..., step_Of_increment).
https://docs.microsoft.com/en-... xchangeadd
А на свою форму поместить таймер (TTimer), который будет с некоторой периодичностью опрашивать состояние этой переменной пусть даже через тот же InterlockedExchangeAdd(..., 0) (т.е. не изменяя значения переменной) и ставить прогресс бар в соответствии с прочитанным значением.

Добавлено через 56 минут
Т.е. например так:
1. Где-то объявляете переменную, видимую из обоих потоков например в классе рабочего потока:
C++
1
2
    public:
        LONG volatile FCounter;
2. Где то в рабочем потоке делаете инкремент этой переменной, например на 10 ед.:
C++
1
InterlockedExchangeAdd(&FCounter, 10)
или даже так:
C++
1
2
if (InterlockedExchangeAdd(&FCounter, 10) == 100)
    InterlockedExchange(&FCounter, 0); // Сбрасываем в 0 при достижении 100%
3. В форму вставляете TTimer и делаете ему интервал обновления скажем 250mS и запускаете его на время обработки файла Excell. В функции таймера делаете :
C++
1
2
3
4
void __fastcall TMyForm::Timer1Timer(TObject *Sender)
{
    ProgressBar1->Position = InterlockedExchangeAdd(&MyThread.FCounter, 0);
}
Можно пойти дальше, сделать в форме переменную с прошлым значением значением OldPosition
Задавать новую позицию погресс бар, только если позиция изменилась.
C++
1
2
3
4
5
6
7
void __fastcall TMyForm::Timer1Timer(TObject *Sender)
{
  LONG NewPosition = InterlockedExchangeAdd(&MyThread.FCounter, 0);
  if (OldPosition != NewPosition)
    ProgressBar1->Position = NewPosition;
  OldPosition = NewPosition
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.04.2019, 11:28
Помогаю со студенческими работами здесь

Сохранение заполненного шаблона word данными из access
Доброго времени суток. Пользуюсь кодом автоматического заполнения шаблона word данными их формы и из запроса методом поиска и замены,...

Автоматический эскпорт информации из "основного" excel файла во вспомогательные и их автообновление
Господа, очень нуждаюсь в вашей помощи! Ситуация такая: Есть основной excel файл (Main.xls) со всей информацией. В первом столбце...

Вызов SaveFileDialog не из основного потока
Есть форма в которой расположен richtextBox для вывода содержимого файла истории сообщений. Хочу снизу формы сделать кнопки: Обновить,...

Вызов основного потока из фонового
Добрый день! Нужно выполнить некий код в отдельном потоке. По завершению выполнения, необходимо вызвать новую форму из ГЛАВНОГО...

Запись в Textbox не из основного потока
Доброе утро. Прошу помочь. Столкнулась со следующей проблемой. Есть элемент формы Textbox в него нужно записывать текст из потока. Получаю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru