Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Завершение процесса Excel из Delphi

Есть такая проблема: в Delphi-форме - объект OleContainer, в него выгружается содержимое рабочей книги Excel. После просмотра того, что выгрузилось, форма закрывается. Но вот вопрос - каким образом завершить процесс Excel, потому что после закрытия формы Excel.exe продолжает занимать память...
Ответ: решил подключать обработку кусками и выяснить на каком этапе происходит затык.
нашел....
Sheet.Range[Sheet.Cells[head+1, 1], Sheet.Cells[head+rows, 12]].UnMerge;
 Sheet.Range[Sheet.Cells[head+1, 1], Sheet.Cells[head+rows, 12]].Sort(Key1:=Sheet.Columns[3], Order1:=1, Key2:=Sheet.Columns[9], Key3:=Sheet.Columns[10]);


сортировка.....
еле-еле ее смог прикрутить, а она торчит.
умеет кто делать сортировку по 3 столбцам?
Вопрос: Как отследить завершение процесса Windows?

Есть программа programma.exe, при запуске которой открывается диалоговое окно выбора изображения, после чего с выбранного изображения считывается информация и записывается в текстовый файл file.txt.
Необходимо написать интерфейс в Delphi к данной программе programma.exe. Замысел заключается в том, чтобы при нажатии на кнопку выполнялись последовательно действия:
1. Запуск programma.exe и создание file.txt.
2. Запись данных из текстового файла file.txt в поля Edit.

Как сделать так, чтобы поля Edit заполнились сразу же после появления file.txt?
Я так понимаю необходимо отследить завершение процесса programma.exe в windows, по завершению которого создается file.txt...

Как сделать двумя кнопками знаю. Через таймер не получится, так как время выполнения programma.exe разное (зависит от того, как долго пользователь выбирает необходимое изображение), теоретически может быть бесконечно долгим.
Ответ: 1. с пом. CreateProcess() запускаешь programma.exe, получаешь хендл созданного процесса
2. с пом. любой подходящей Wait-функции (например, WaitForSingleObject) ждешь его завершения
3. закрываешь полученный на шаге 1 хендл
Вопрос: Отследить завершение процесса программы

Здравствуйте. Роюсь-роюсь, никак не дороюсь.
Запускаю программу, появляется процесс. (логично)
Хочу иметь возможность как-то отследить принудительное завершение процесса программы. Ну или хотя бы просто завершение процесса... Никак не удаётся.
Кто может подсказать: что надо написать, чтобы было событие на завершение процесса программы?
Ответ: разобрался вроде бы. если кому интересно будет:
в Program.cs перед строчкой:
C#
1
Application.Run
вставляем:
C#
1
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
и добавляем после:
C#
1
2
3
4
static void Main()
{
//что тут у Вас
}
это:
C#
1
2
3
4
static void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            //запись лога, например.
        }
при завершении процесса, конечно, не срабатывает...
но срабатывает при всех без исключения выхода из программы. (в т.ч. в случае ошибке вне "try")
Вопрос: Как закрыть процесс Excel?

Добрый день.
Не могу решить следующую проблему:
Создаю экземпляр Excel, открываю файл, закрываю его. В результате в task manager все равно остается висеть процесс Excel.exe. Он пропадает только после полного закрытия приложения.
Вот код:

Код C#
1
2
3
4
5
 Microsoft.Office.Interop.Excel.Application excelapp = new Microsoft.Office.Interop.Excel.Application();
            excelapp.Workbooks.Open(System.Windows.Forms.Application.StartupPath + "\\Шаблон1.xlsx", Type.Missing, false, Type.Missing, Type.Missing, Type.Missing, true, Type.Missing,
                 Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing)
 
excelapp.Quit();
Подскажите пожалуйста как закрыть так, чтобы из процессов также убралось?
Ответ: Так как вопросы ещё есть, хочу попробовать подвести итог, моей эпопеи с не убиваемым(на самом деле убиваемым) Excel приложением.
Вообще если есть возможность (Если нужно, например, забить ячейки Excel какой-нибудь инфой) то я бы советовал использовать SQL запросы.
Если же нужно редактировать стиль ячеек (границы, свет и т.д. и т.п.) то без библиотеки
Microsoft.Office.Interop.Excel не обойтись
Ну и так об Microsoft.Office.Interop.Excel,
Вот мой кодик. Всё отлажено, Excel процесс не висит.
Всё хорошо работает, если приложение уже было открыто, если приложение не было открыто и если в процессе работы нашей программы пользователь открыл другу книгу.
Такс такс, что ещё... Библиотеку Microsoft.Office.Interop.Excel я использовал версии 12. Специально использовал относительно старенькую версию. В других версиях работа с книгами, листами, ячейками может отличаться. Точно помню, что в 14 версии по-другому выбираются ячейки.
Раньше PhoenixJack писал Сборщик мусора не срабатывает, если есть ссылки на приложение Excel.Вот в примере.
Я давно это пробовал, но почему-то у меня всё равно процесс висел в памяти. Может не все ссылки удалял, а может, чем чёрт не шутит, зависит и от версии библиотеки Microsoft.Office.Interop.Excel
Ну в общем вот:
Код 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;   
using System.Runtime.InteropServices;
 
namespace KILLEXCEL
{
    public partial class Form1 : Form
    {
        public Excel.Application excelApp;          
        public Excel.Range excelCells;
        public Excel.Sheets excelSheets;
        public Excel.Worksheet excelWorkSheet;
        public Excel.Workbooks excelAppWorkbooks;
        public Excel.Workbook excelAppWorkbook;
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {// Присоединение к открытому приложению Excel (если оно открыто), имхо так тру, ибо 2 excel процесса в памяти не кошерно
                excelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
            }
            catch
            {
                excelApp = new Excel.Application(); // Если нет открытого, то создаём новое приложение
            }
            excelApp.Visible = true;                // Делаем приложение видимым
            excelApp.SheetsInNewWorkbook = 3;       // В новой созданной книге будет 3 листа
            excelApp.Workbooks.Add(Type.Missing);   // Добавляем книгу
            excelAppWorkbooks = excelApp.Workbooks; // Получаем список открытых книг
            excelAppWorkbook = excelAppWorkbooks[excelAppWorkbooks.Count];  // Устанавливаем ссылку на нашу книгу и да именно Count, а не Count-1, так как отсчёт идёт с 1!!!!!!
            excelSheets = excelAppWorkbook.Worksheets; // Получаем список листов в нашей книге
            excelWorkSheet = (Excel.Worksheet)excelSheets.get_Item(1);  // Берем первый лист
            excelCells = excelWorkSheet.get_Range("A1", "A1");          // Берём ячейку А1
            excelCells.Value2 = "HiCyberForum";                         // Пишем в неё что-нибудь
            // Далее опишу закрытие, для того что-бы не висел процесс в памяти, нужно обнулить ВСЕ! ссылки, которые связаны с библиотекой Microsoft.Office.Interop.Excel
            excelCells = null;
            excelWorkSheet = null;
            excelSheets = null;
            try
            {// Тут уж простите за заплатку, выпадало исключение, если файл с таким именем существует и пользователь откажется перезаписывать его
                // Не знаю почему, времени нет разбираться.
                excelAppWorkbook.Save();
            }
            catch { }
            excelAppWorkbook.Close(false, false, false);// Закрываем книгу
            excelAppWorkbooks = excelApp.Workbooks;     // Далее проверяем есть ли ещё другие открытые книги, ведь во время работы нашей программы пользователь мог открыть другую книгу
            if (excelAppWorkbooks.Count == 0)
                excelApp.Quit();            // Если нет то закрываем приложение
            excelAppWorkbook = null;        // Продолжаем обнулять ссылки
            excelAppWorkbooks = null;
            excelApp = null;
            GC.Collect();       // Зовём МистераПропера на помощь
            // С MSDN: Сборке мусора подвергаются все объекты, вне зависимости от времени их нахождения в памяти. Однако объекты, на которые имеются ссылки в управляемом коде, не освобождаются. Используйте этот метод, чтобы принудительно предпринять попытку высвободить максимальный объем доступной памяти.
        }
    }
}
Вопрос: Excel + Delphi

Отцы! Проблему кое-как поборол, спасибо, но у меня новая проблема:

begin
	Excel.Modules.Add(EmptyParam, EmptyParam, 1);
	temp := 'Sub mymacros()' + #13;
	temp := temp + 'Dim a As Workbook' + #13;
	temp := temp + 'Dim lLastRow As Long' + #13;
	temp := temp + 'Dim i As Long' + #13;
	temp := temp + 'Set a = ThisWorkbook' + #13;
	temp := temp + 'lLastRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count' + #13;
	temp := temp + 'Application.ScreenUpdating = False' + #13;
	temp := temp + 'For i = lLastRow To 1 Step -1' + #13;
	Query1.Open;
		while not Query1.Eof do
			begin
			fio:=Query1.FieldByName('fio').AsString;
			ordinal:=Query1.FieldByName('ordinal').AsString;
			temp:=temp + 'if a.Sheets("sheet1").Cells(i, 6).Text like "' + fio + '*" then a.Sheets("sheet1").Cells(i, 6) = "' + ordinal + '"' + #13;
			Query1.Next;
			end;
	temp:=temp + 'Next i' + #13;
	temp:=temp + 'End Sub' + #13;
	WorkBook.VBProject.VBComponents.Item(1).Codemodule.AddFromString(temp);
	Excel.Run('mymacros');
	CMod:=Excel.ActiveWorkbook.VBProject.VBComponents.Item(1).CodeModule;
	StartLine:=CMod.ProcStartLine['mymacros', 0];
		if StartLine > 0 then
			begin
			LineCount:=CMod.ProcCountLines['mymacros', 0];
			CMod.DeleteLines(StartLine, LineCount);
			end;
	Query1.Close;
end;


Из БД (поле 'fio') вытягиваются пользователи, и я с ними шаманю уже в пределах xls-файла. Когда пользователей было ~300 - всё было хорошо, макрос отрабатывал без единой ошибки, быстро и чётко. Но после расширения пользователей стало ~3000, и макрос выпадает с печально известной vba-ошибкой "procedure too large" :(

Уменьшаю количество пользователей - программа работает, увеличиваю - программа не работает.



p.s.
Да, у меня нет ответа на классический вопрос "а причём тут Delphi?", но может кто-нибудь подскажет, как можно этот макрос разбить на два или просто обойти такую ошибку? Макрос мой, каюсь, безобразный и без того уже урезан до предельного минимума, но я, признаться, не силён ни в Delphi, ни в Excel, поэтому и беспокою вас сейчас.
Ответ:
Gator
каким образом ты получаешь эти "тысячи ФИО и их id" из базы.
И какой идиот согласится править (дополнять) твой Макрос? Ешщё миллионом строк...
Вопрос: Переименование листа в Excel. (Delphi)

Нужо создать книгу с 1 листом. Задать листу имя. Сохранить книгу.

XL := CreateOLEObject('Excel.Application'); 
             XL.SheetsInNewWorkbook := 1;
              XL.WorkBooks.add;
              XL.WorkBooks.WorkSheet[1].Name := 'test';
              XL.DisplayAlerts := false;
              XL.ActiveWorkBook.SaveAs('с:\book.xls');
              XL.Quit;
            XL := Unassigned;


EOLeError with message 'Method 'WorkSheet' not supported by automation object'.
Ответ: XLSss,
XL.Columns[1].NumberFormat := '0'
Вопрос: Создать процесс Excel так, чтобы пользователь никак его не смог испортить.

Текущая ситуация:
    Dim oExcelApp As New Excel.Application  'Приложение.
    Dim oDocExcel As New Excel.Workbook 'Документ Excel.
    Dim oExWs As New Excel.Worksheet 'Таблица документа Excel.
     
     Set oExcelApp = New Excel.Application
     oExcelApp.Visible = False
     Set oDocExcel = oExcelApp.Workbooks.Open(g_oCommonDialog.FileName, , True)
     Set oExWs = oDocExcel.ActiveSheet
     
    ...
     
     Call oDocExcel.Close(False)
     Call oExcelApp.Quit
     
     If Not oExWs Is Nothing Then Set oExWs = Nothing
    If Not oDocExcel Is Nothing Then Set oDocExcel = Nothing
    If Not oExcelApp Is Nothing Then Set oExcelApp = Nothing


Но есть проблема. Если пользователю приспичит открыть какой-нибудь документ Excel - он откроется именно в этом процессе. И если пользователь закроет Excel - уничтожится и процесс - все поломается.

То есть, Visible = false - не спасение.

Как заблочить Excel.exe от внешнего вмешательства?
Ответ:
Неа.

27 Set oExcelApp = New Excel.Application
28 oExcelApp.Visible = False
oExcelApp.IgnoreRemoteRequests = True

Добавлено
Цитата leo @


Добавлено
Уйё. Надо возвращать в False при выходе из программы или фатальной ошибке. Иначе все остальные процессы Excel тоже оказываются заблоченными. Посмотрим, поможет ли перезагрухка.

Добавлено
Ахаха, полный треш: перезагрузка НЕ помогает, пока кодом обратно в False не вернешь. В общем, эффективный способ - если быть предельно аккуратным.
Вопрос: Процесс Excel

Смысл достаточно прост.
По ходу написания приложения возникла необходимость работать с Excel через C#.
Задача следующая - запустить книгу Excel, а когда её закроют процесс Excel должен умереть.
Проблема - открываю книгу, обнуляю объекты, когда книгу закрывают руками - процесс остается висеть.
Код вот такой, условие на if значения не имеет.
C#
1
2
3
4
5
6
7
8
9
10
if (!Flag)
                {
                    Excel.Application ec = new Excel.Application();
                    Excel.Workbook some = ec.Workbooks.Open(FormInformation.Folder, true, false);
                    ec.Visible = true;
                    ec.UserControl = true;
                    ec = null;
                    some = null;                  
                }
                GC.Collect();
Разве этого недостаточно для сборщика мусора? Что еще необходимо?
Ответ: Зачем здесь деструкторы? Они должны сделать то же, что и за-null-ение объекта. Использовал
C#
1
2
Marshal.ReleaseComObject(ec);
Marshal.ReleaseComObject(some);
Не помогло.
Причем, что интересно в другой части программы использовал абсолютно аналогичный метод, там он работает, а в этой части кода нет.
Вопрос: Как завершить процесс Excel после работы с ним?

Суть вот в чем: программа берет некоторые данные из файла Excel после чего закрывает его. Но процесс Excel продолжает висеть до заверешения программы. Я перепробовал уже кучу вариантов, ни один не подходит.
vb.net
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Dim oExcel As Excel.Application
Dim oBook As Excel.Workbook
Dim oSheet As Excel.Worksheet
 oExcel = New Excel.Application
 oExcel.Visible = False
 oBook = oExcel.Workbooks.open(.FileName)
 oSheet = oBook.Worksheets(1)
 oSheet.Activate()
' Тут берем данные с листа и творим всякие непристойности
 oSheet = Nothing
 oBook.Close(SaveChanges:=False)
 oBook = Nothing
 oExcel.Quit()
 oExcel = Nothing
 GC.Collect()
Ответ: Pe4eNEG,
Вопрос: "Висящий" процесс Excel.exe

Доброго времени суток, господа!
Возник следующий вопрос...

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

Пробелма в следующем, при любом раскладе всегда остается "висящим" процесс excel.exe, который завершается только после того, как будет закрыта сама программа прожект.ехе.

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

файлы .xls открываются и закрываются следующим образом:

Visual Basic
1
2
3
4
5
6
Workbooks.Open FileName:="С:\файл1.xls"
------------------------------------------------
обрабатываем файлик
------------------------------------------------
ActiveWorkbook.SaveAs FileName:="С:\файл1.xls"
ActiveWorkbook.Close SaveChanges:=False
п.с. на картинке показано какие библиотеки подключены..
п.с.с. команда Application.Quit - не помогает убить процесс.



Спасибо за советы\подсказки!!!
Ответ: Казанский, спасибо! Будем работать дальше

Добавлено через 1 час 52 минуты
Возникла вот такая ошибка...
В этом случае максимальное кол-во используемых строк в файле определяется адекватно, 55 штук к примеру
Visual Basic
1
2
3
4
5
6
7
With xlApp
    .Workbooks.Open FileName:="C:\file1.xls"
    .ActiveWorkbook.Sheets("List").Select
    With .ActiveWorkbook.ActiveSheet
        LRPROC = xlApp.ActiveWorkbook.ActiveSheet.UsedRange.Row - 1 + xlApp.ActiveWorkbook.ActiveSheet.UsedRange.Rows.Count
    End With
End With
а в этом определяет = 1

Visual Basic
1
2
3
4
5
6
7
With xlApp
    .Workbooks.Open FileName:="C:\file1.xls"
    .ActiveWorkbook.Sheets("List").Select
    With .ActiveWorkbook.ActiveSheet
        LRPROC = .UsedRange.Row - 1 + .UsedRange.Rows.Count
    End With
End With
Добавлено через 38 минут
п.с. в процессе работы получается так, что во втором случае программа видит пустой лист, хотя на самом деле данные в нем есть, почему так происходит не понятно...
даже если проверить через msgbox
Visual Basic
1
2
3
With xlApp.ActiveWorkbook.ActiveSheet
MsgBox (xlApp.ActiveWorkbook.ActiveSheet.Cells(15, 2))' - так выдает содержимое ячейки
end with
Visual Basic
1
2
3
With xlApp.ActiveWorkbook.ActiveSheet
MsgBox (.Cells(15, 2))' - а вот так оно пустое
end with
Добавлено через 28 минут
на первом(начальном листе) заполнена только первая строка, а на втором( на который происходит переключение) 55 строк, на деле выходит что программа не хочет переключаться на другой лист, поэтому и выдает значение = 1
непонятно как то.
Visual Basic
1
2
3
With xlApp.ActiveWorkbook.ActiveSheet
MsgBox (xlApp.ActiveWorkbook.ActiveSheet.Cells(15, 2))' - так выдает содержимое ячейки
end with
таким способом она выдает значение с нужного листа, т.е. переключилась
Visual Basic
1
2
3
With xlApp.ActiveWorkbook.ActiveSheet
MsgBox (.Cells(15, 2))' - а вот так оно пустое
end with
а так нет, тянет с первого листа, как такое может быть?