QuickScript .NET — различия между версиями

Материал из archestra.info
Перейти к: навигация, поиск
(Application Server)
(Примеры Application Server 3.5 + Microsoft Excel 2007)
Строка 82: Строка 82:
 
LogMessage("2 end");
 
LogMessage("2 end");
 
</pre>
 
</pre>
 +
 +
'''Очистка ресурсов после выгрузки данных в Excel'''
 +
Источник: http://www.sql.ru/forum/906372/dlya-chego-nuzhen-marshal-releasecomobject
 +
 +
                appl.Quit();
 +
                System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
 +
                System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
 +
                System.Runtime.InteropServices.Marshal.ReleaseComObject(appl);
 +
 +
                worksheet = null;
 +
                workbook = null;
 +
                appl = null;
 +
                System.GC.Collect();
 +
 +
* Т.е. предложенный способ очистки ресурсов - корректный?
 +
** Не вполне. В конце после вызова System.GC.Collect() не хватает еще GC.WaitForPendingFinalizers().
 +
* К чему приведет неиспользование данного метода?
 +
**Попробуйте сгениерить через интероп экселевский документ эдак на 50 тысяч строк раз 10-20-30. И понаблюдайте за памятью. Достаточно обычная * Следует ли применять данный метод к объектам Range?
 +
** Мало того, что к Range - это такой же com-объект, как и все прочие при работе через интероп. Желательно делать свои обертки для всех используемых объектов, и обертки эти делать с реализацией IDisposable, в которых Dispose будет освобождать память по подобному сценарию. Нужно это потому, что при работе с интероп сплошь и рядом имеет место быть неявное создание ссылок на com-объекты - например, вы получаете ссылку на Selection, и работаете с Selection.Range; при этом создается неявная ссылка на Selection.Range, которую GC не подбирает. Обертка, разумеется, ведет контроль за созданием подобных ссылок.

Версия 10:18, 9 сентября 2013

InTouch

QuickScript .NET (для Application Server)

Работа с MS Excel

SR30711946: How to maximize an excel application? Use WWControl()


Описание объектной модели

Самым "верхним" объектом в Excel является объект Application. Это объект приложение. И этот объект содержит ряд коллекций. Коллекция в VBA - это что-то вроде массива, только элементы в нее можно добавлять и удалять во время выполнения программы. Рабочие книги Excel входят в коллекцию Workbooks. Чтобы узнать количество открытых книг, используется метод Workbooks.Count.

Добавить новую книгу можно вызвав метод Workbooks.Add(). В качестве параметра этому методу можно передать имя шаблона, на основе которого будет создаваться новая книга. Чтобы открыть существующий файл Excel, вызывается метод Workbooks.Open("file.xls") - в результате будет открыт файл file.xls.

Закрыть книгу можно так: Workbooks(1).Close, или так: Workbooks("Книга1").Close, или закрыть все книги сразу: Workbooks.Close. Метод Close имеет ряд необязательных параметров. Вот они. expression.Close(SaveChanges, FileName, RouteWorkbook) Первый параметр SaveChanges имеет тип BOOL, если он равен TRUE, сделанные изменения сохранятся, если FALSE - то нет. Если параметр не задан, то при закрытии появляется диалоговое окно с вопросом о необходимости сохранения. Save changes ?

К книгам в коллекции можно обращаться через метод Item():

Sub Test()

 s1 = Application.Workbooks.Item(1).Name
 s2 = Application.Workbooks.Item("book.xls").FullName

End Sub

Доступ к книге можно получить по индексу и по имени книги. Имя книги - это имя файла, в котором она хранится. Fullname содержит полное имя, название файла и путь, а Name - только имя.


Примеры Application Server 3.5 + Microsoft Excel 2007

Dim app As Object;

Dim wb As Object;

Dim ws As Object;



app = CreateObject("Excel.Application");

LogMessage("Before wb add");

wb = app.Workbooks.Add();

LogMessage("After wb add");

LogMessage("before activesheet add");

ws = wb.ActiveSheet;

LogMessage("After activesheet add");

LogMessage("get range A1");

ws.Range("A1").Value = 1000;

LogMessage("get range A2");

ws.Range("A2").Value = 1000;

LogMessage("get range A3");

ws.Range("A3").Value = "=A1+A2";
LogMessage(ws.Range("A3").Value);
LogMessage("close");

wb.SaveAs("c:\temp\Book1.xlsx");
LogMessage("saved");
wb.Close(false);


LogMessage("2");
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws );

System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);

app.Quit();

System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

System.GC.Collect();
LogMessage("2 end");

Очистка ресурсов после выгрузки данных в Excel Источник: http://www.sql.ru/forum/906372/dlya-chego-nuzhen-marshal-releasecomobject

               appl.Quit();
               System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
               System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
               System.Runtime.InteropServices.Marshal.ReleaseComObject(appl);
               worksheet = null;
               workbook = null;
               appl = null;
               System.GC.Collect();
  • Т.е. предложенный способ очистки ресурсов - корректный?
    • Не вполне. В конце после вызова System.GC.Collect() не хватает еще GC.WaitForPendingFinalizers().
  • К чему приведет неиспользование данного метода?
    • Попробуйте сгениерить через интероп экселевский документ эдак на 50 тысяч строк раз 10-20-30. И понаблюдайте за памятью. Достаточно обычная * Следует ли применять данный метод к объектам Range?
    • Мало того, что к Range - это такой же com-объект, как и все прочие при работе через интероп. Желательно делать свои обертки для всех используемых объектов, и обертки эти делать с реализацией IDisposable, в которых Dispose будет освобождать память по подобному сценарию. Нужно это потому, что при работе с интероп сплошь и рядом имеет место быть неявное создание ссылок на com-объекты - например, вы получаете ссылку на Selection, и работаете с Selection.Range; при этом создается неявная ссылка на Selection.Range, которую GC не подбирает. Обертка, разумеется, ведет контроль за созданием подобных ссылок.