Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

2006 г.

Excel ЧаВо

Александр Шабля, Королевство Delphi
Все вопросы Worksbooks и Worksheets Cells, Range, Rows и Columns Chart, Shape, Picture Внешние источники данных

Excel.Application


Excel.Application

Excel Range Object


Как загрузить новый экземпляр Excel или подключиться к запущенному экземпляру EXCEL.EXE? Как отсоединиться от Excel и закрыть его экземпляр?

Для определения, будет ли запущен новый экземпляр Excel.Application или присоединение к уже запущенному, используется свойство TExcelApplication.ConnectKind. По умолчанию это свойство имеет значение ckRunningOrNew (константы определены в unit OleServer). Однако рекомендуется, если нет на то особой надобности, всегда запускать новый экземпляр Excel.Application во избежание конфликтов с запущенным раннее экземпляром Excel.Application. Свойство TExcelApplication.AutoQuit в конструкторе устанавливается по умолчанию в False (только в модуле ExcelXP в True) — это значит, что если вы хотите при отсоединении завершить работу Excel (закрыть), то нужно вызвать метод TExcelApplication.Quit или установить свойство TExcelApplication.AutoQuit равным True.

Delphi:

var
  XL: TExcelApplication;
begin
  // запускаем новый экземпляр Excel'я
  XL := TExcelApplication.Create(nil);
  try

    XL.ConnectKind := ckNewInstance;
    XL.Connect; // подключение
    XL.AutoQuit := False; // по умолчанию это свойство True только в unit ExcelXP
    XL.Visible[lcid] := True;
    // здесь работаем с Excel'ем
  finally
    // отсоединяемся

    XL.UserControl := True; // отдадим управление пользователю
    XL.Quit; // закрыть Excel
    XL.Disconnect;
    FreeAndNil(XL);
  end;

C#:

private Excel.Application StartExcel(bool asNewInstance)
{
	Excel.Application XL = null;
	if (!(asNewInstance)) {
		try {
			XL = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
				as Excel.Application;
		}
		catch {
			// XL = null;
		}
	}
	if (XL == null) XL = new Excel.Application();
	if (XL.Workbooks.Count == 0) XL.Workbooks.Add(Type.Missing);
	XL.Visible = true;
	return XL;
}
private void FinishExcel(Excel.Application XL)
{
	if (XL != null) {
		XL.ScreenUpdating = true;
		if (! XL.Interactive) XL.Interactive = true;
		XL.UserControl = true;
		if (XL.Workbooks.Count == 0) {
			XL.Quit();
		}
		else {
			if (! XL.Visible) XL.Visible = true;
			XL.ActiveWorkbook.Saved = true;
		}
		// System.Runtime.InteropServices.Marshal.ReleaseComObject(XL);
		XL = null;
		GC.GetTotalMemory(true); // вызов сборщика мусора
		// Пока не закрыть приложение EXCEL.EXE будет висеть в процессах
	}
}

How to automate Microsoft Excel from Microsoft Visual C# .NET

How to use Visual C# to automate a running instance of an Office program

GC.GetTotalMemory Method

GC Class


Как запустить Excel из консольного приложения или в отдельном потоке (TThread)

Консольное приложение и дочерний поток (класс TThread) не предполагают работу с COM сервером, как это сделано в главном потоке для Application в VCL. Для того чтобы все работало, необходим вызов функции WinAPI CoInitialize.

{$APPTYPE CONSOLE} // для консольного приложения
var
  NeedToUninitialize: Boolean;
…
begin
//  NeedToUninitialize := Succeeded(CoInitialize(nil));
  NeedToUninitialize := Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED));
  try

    // здесь работаем с Excel'ем
  finally
    if NeedToUninitialize then CoUninitialize;
  end;
end.

Отличие при работе в Thread — весь код работы должен быть помещен в метод TThread.Execute.

Для C# ничего дополнительно вызывать не нужно — все работает, что для WinForms, что для Console, что для объекта класса Thread().

CoInitializeEx

OleInitialize


Как получить и настроить папки Excel по умолчанию?

По умолчанию все открываемые и сохраняемые документы находятся в папке "%USERPROFILE%Мои документы" (Personal). Ссылка на эту папку содержится в свойстве TExcelApplication.DefaultFilePath (read/write). Для чтения и записи в другие папки используйте полный путь к файлу книги.

Delphi:

(XL.ActiveSheet as _Worksheet).Range['A1', EmptyParam].Formula :=
      Format('DefaultFilePath: %s', [XL.DefaultFilePath[lcid]]);

DefaultFilePath Property

How to: Set the Default Save Path for Workbooks


Чем отличается TExcelApplication от ExcelApplication, TExcelWorkbook от ExcelWorkbook?

Все отличие TExcelApplication от ExcelApplication в том, что первый — наследник TOleServer. Это расширяет возможности для выбора способа подключения/отключения COM-сервера Excel и упрощает работу с событиями Excel.Application. Получить интерфейс ExcelApplication всегда можно из свойства TExcelApplication.DefaultInterface (DefaultInterface — штатное свойство всех наследников класса ToleServer).


Как узнать локализацию Excel'я (русская версия или нет)?

Для Delphi это можно почитать здесь.

C#:

oSheet.get_Range("A1", Type.Missing).Value2 =
  XL.LanguageSettings.get_LanguageID(
  Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI);

LanguageSettings Object


Как сделать, чтобы Excel работал быстрее?

Для ускорения работы с Excel'ем можно сделать следующие шаги:

Delphi:

// запретить перерисовку экрана
XL.ScreenUpdating[lcid] := False;

// отменить автоматическую калькуляцию формул

XL.Calculation[lcid] := xlManual;

// отменить проверку автоматическую ошибок в ячейках (для XP и выше)
    with XL.ErrorCheckingOptions do begin
      BackgroundChecking := False;
      NumberAsText := False;
      InconsistentFormula := False;
    end;

Не использовать метод Select, и, как следствие, свойство Selection (смотрите дальше).

Существенно повышается скорость, если вместо записи в каждую ячейку использовать запись из VarArray (смотрите дальше про объект Range). В Demo-проекте есть тест затраченного времени для различных методов записи.

Так как основное время работы с Excel'ем затрачивается на перерисовку (установка отступов для страницы, размеров строк и столбцов, атрибуты шрифтов и т.д.), то лучше всего использовать заранее подготовленный шаблон.


Как вывести приложение Excel на передний план?

Для "выноса" приложения Excel на передний план просто вызовите метод Visible объекта ExcelApplication.

Delphi:

XL.Visible[lcid] := True;
// Этот способ только для Excel версии XP и выше

SetForegroundWindow(XL.Hwnd);

C#:

XL.Visible = true;

Как сделать так, чтоб работали английские формулы и форматы чисел в ячейках?

Решение для Delphi здесь "Русский Excel и установка NumberFormat"

К сожалению, при работе с русским Excel'ем из C# проблемы те же, но, к счастью, решаются проще — через CultureInfo:

C#:

int savedCult = Thread.CurrentThread.CurrentCulture.LCID;
try {
  // установим английскую "культуру"
  Thread.CurrentThread.CurrentCulture = new CultureInfo(0x0409, false);
  Thread.CurrentThread.CurrentUICulture = new CultureInfo(0x0409, false);
// здесь работаем с Excel'ем, при чем работают английские формулы, DataFormat 
// и колонтитулы в PageSetup
finally {
// восстановим пользовательскую "культуру" для отображения всех данных в
// привычных глазу форматах
  Thread.CurrentThread.CurrentCulture = new CultureInfo(savedCult, true);
  Thread.CurrentThread.CurrentUICulture = new CultureInfo(savedCult, true);
}

Русский Excel и установка NumberFormat

How to: Set the Culture and UI Culture for Windows Forms Globalization


Что такое Selection?

Как пишут в "Best Practices for Setting Range Properties": "Код, использующий Selection, сгенерирован записью макроса Excel, часто используется для обнаружения объекта или метода, который будет работать. Это хорошая идея, за исключением того, что записанный макрос не оптимизирован для пользователя. Обычно Excel при записи макроса использует Selection и изменяет выбор объекта при записи какой либо задачи".

Т.е. использование Selection не является обязательным и даже не рекомендуется для разработчика. Цитата оттуда же: "На практике вызывайте метод Select объекта только тогда, когда твердо намерены изменить выбранный пользователем элемент. Вы можете никогда не использовать метод Select просто потому, что это вам удобно, как разработчику. Если вы устанавливаете свойства объекта Range, у вас всегда есть альтернатива. Отказ от метода Select не только делает ваш код быстрее, но и порадует пользователей вашей программы (it makes your users happier)". Эта тема еще затронута здесь.

Selection Property


Почему не нужно использовать Excel.Application.Range, а следует ExcelWorksheet.Range?

Использование ExcelApplication.Range позволяет работать только с активным листом активной книги. Если вы открываете по ходу работы еще одну книгу или делаете активным другой лист в книге (например, добавляете новый лист), то данные будут вноситься именно в активный в данный момент лист. Чтоб не попасть в неудобную ситуациюб всегда используйте объект Range объекта ExcelWorksheet. Это не только обезопасит ваш код от попадания "куда Бог пошлет", но и позволит записывать данные сразу в несколько листов и даже книг без изменения ActiveSheet и ActiveCell.


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

При работе с запущенным приложением Excel, он может быть занят, если в это время пользователь редактирует значение в ячейке, или в нем открыто какое-либо модальное диалоговое окно (например, "Открытие документа"). Чтобы обойти эту ситуациюб всегда запускайте новую копию Excel.Application и устанавливайте свойство Interactive в False, что запретит пользователю что-либо делать в Excel'е или закрыть запущенный экземпляр Excel.Application:

Delphi:

XL := TExcelApplication.Create(nil);

try
  XL.ConnectKind := ckNewInstance;
  XL.Connect;
  XL.Interactive[lcid] := False; // запрещаем работу пользователю с нашим экземпляром Excel'я
  XL.Visible[lcid] := True;
// работать здесь
finally
  // не забыть разрешить пользователю доступ к Excel'ю!
  XL.UserControl := True;
  XL.Interactive[lcid] := True;
  XL.Disconnect;
  FreeAndNil(XL);

end;

The action cannot be completed because Microsoft Office Excel is busy

Interactive Property


Экспорт в Excel длится довольно долго. Как можно уведомлять пользователя о ходе выполнения работы?

Чтобы пользователь не подумалб что во время экспорта данных в Excel ваша программа и Excel "висит", лучше уведомлять его о ходе работы. Т.к. обновление экрана занимает довольно много времени и так довольно длительного процесса экспорта (хотя все же стоит подумать, как этот процесс оптимизировать и ускорить), то лучшим выходом из этой ситуации является показ этапов работы в свойстве ExcelApplication.StatusBar:

Delphi:


XL.DisplayStatusBar[lcid] := True; // покажем StatusBar, если его не было видно
XL.StatusBar[lcid] := 'Читаем';
//
XL.StatusBar[lcid] := 'Пишем';
//
XL.StatusBar[lcid] := 'Считаем';
//

XL.StatusBar[lcid] := False; // уберем наше последнее сообщение

C#:

XL.DisplayStatusBar = true;
//
XL.StatusBar = "Текст в статусбаре";
//
XL.StatusBar = false; // "Готово"

DisplayStatusBar Property

StatusBar Property


Переношу записанный VBA макрос рисования границы в Excel, но Delphi не знает что такое xlContinuous. Где взять значение этой константы?

Это всего лишь значит, что вы пользуетесь в Delphi поздним связыванием. Добавьте в uses ExcelXP или Excel2000. Для C# нужно полностью указывать namespace, тип и имя этой константы, например Excel.XlLineStyle.xlContinuous.

Microsoft.Office.Interop.Excel Namespace


Почему я не могу найти описание компонентов палитры Delphi "Servers" в Help'е? Где найти документацию по работе с Excel'ем?

Компоненты на палитре "Servers" — это "обертка" (wrapper) популярных COM-серверов Microsoft. Для описания их объектной модели, свойств и методов используйте поставляемый с Microsoft Office VBA Help или ищите информацию на MSDN (также смотрите "Полезные ссылки" в конце).

Microsoft Excel Object Model

Automating Excel Using the Excel Object Model

Office Development — Excel

Migrating Excel VBA Solutions to Visual Studio 2005 Tools for Office

Converting Microsoft Office VBA Macros to Visual Basic .NET and C#

Microsoft Excel 2003 Language Reference

Understanding the Excel Object Model from a .NET Developer's Perspective

Microsoft.Office.Interop.Excel Namespace

Excel Objects

Code Examples for Excel (C#)


Все вопросы Worksbooks и Worksheets Cells, Range, Rows и Columns Chart, Shape, Picture Внешние источники данных

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...