Функции работы из 1с 8.х с EXCEL (объекная модель)

Опубликовал Дмитрий Воробьев (vde69) в раздел Программирование - Практика программирования

Надоели вопросы по ошибкам при работе с екселем, даю базовые функции, для работы.
Постю, что-бы удобнее было давать ссылку, а не искать каждый раз в конфе.

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


// функция устанавливает связь с EXCEL
// в качестве параметра требуется имя открываемого файла
// в случае удачи возвращает соответствие из обьектов ОЛЕ, в случае не удачи - неопределено
Функция   EXCEL_УстановитьСвязь (ИмяФайла)Экспорт
	
	Результат = Неопределено;
	#Если Клиент Тогда
		Состояние("Идет установка связи, ждите.....");
	#КонецЕсли
	
	Попытка
		Результат = Новый Соответствие();
		
		BaseOLE = Новый COMОбъект("Excel.Application");
		Результат.Вставить("EXCEL", BaseOLE);
		
		ExcelФайл = BaseOLE.WorkBooks.Open (ИмяФайла);
		Результат.Вставить("ExcelФайл", ExcelФайл);
		                		
		МассивЛистов = Новый Массив();
		КоличествоЛистов = ExcelФайл.Sheets.Count;
		Для е = 1 по КоличествоЛистов Цикл
			МассивЛистов.Добавить(ExcelФайл.Sheets(е));			
		КонецЦикла;
		
		Результат.Вставить("Листы", МассивЛистов);

	Исключение
		Результат = Неопределено;
		#Если Клиент Тогда
			Сообщить("Ошибка создания обьекта Microsoft Excel" + ОписаниеОшибки());
		#КонецЕсли
	КонецПопытки;
	
	Возврат Результат;
КонецФункции

// функция разрывает связь с 1с 7.7
// в качестве параметра требуеться структура созданая при установке соединения 
Процедура EXCEL_РазорватьСвязь (Соответстие) Экспорт
	Попытка
		Соответстие["EXCEL"].DisplayAlerts = 0;
		Соответстие["ExcelФайл"].Close();
		Соответстие["EXCEL"].DisplayAlerts = 1;
		Соответстие["EXCEL"].Quit(); 
		Соответстие["EXCEL"] = Неопределено;
	Исключение
		#Если Клиент Тогда
			Сообщить(ОписаниеОшибки());
		#КонецЕсли
	КонецПопытки;                  
КонецПроцедуры


// функция получает данные ячейки и возвращаеть структуру соответствий, или неопределено в случае неудачи
//
// В любом случае возвращаем соостветствие "Значение" и "ЭтоФормула", остальное по флагам
//
Функция EXCEL_ПолучитьЗначениеЯчейки (ExcelЛист, НомерСтроки, НомерКолонки, ПолучатьТекстФормулы = ложь, ПолучатьОформление = ложь) 
	Результат = Новый Соответствие();
	
	Попытка
		ТекущееЗначениеФормулы = ExcelЛист.Cells(НомерСтроки, НомерКолонки).Formula;
		Если ТекущееЗначениеФормулы <> "" Тогда
			Если Лев(ТекущееЗначениеФормулы, 1) <> "=" Тогда 
				Результат.Вставить("ЭтоФормула", Ложь);
				Результат.Вставить("ЗначениеЯчейки", ExcelЛист.Cells(НомерСтроки, НомерКолонки).value);
			Иначе
				Результат.Вставить("ЭтоФормула", Истина);
				Если Лев(СокрЛП(ExcelЛист.Cells(НомерСтроки, НомерКолонки).text),1) = "#" Тогда 
					Результат.Вставить("ЗначениеЯчейки", Неопределено);
				Иначе
					Результат.Вставить("ЗначениеЯчейки", ExcelЛист.Cells(НомерСтроки, НомерКолонки).value);
				КонецЕсли;

				Если ПолучатьТекстФормулы Тогда  
					Результат.Вставить("ТекстФормулы", СокрЛП(ТекущееЗначениеФормулы));
				КонецЕсли;
			КонецЕсли; 
		Иначе
			Результат.Вставить("ЭтоФормула", Ложь);
			Результат.Вставить("ЗначениеЯчейки", ExcelЛист.Cells(НомерСтроки, НомерКолонки).value);
		КонецЕсли;    
		
		Если ПолучатьОформление Тогда
			Результат.Вставить("ЦветЯчейки", СокрЛП(ExcelЛист.Cells(НомерСтроки, НомерКолонки).Interior.ColorIndex));
			// здесь можно добавить и другие....
		КонецЕсли;
		
	Исключение
		Результат = Неопределено;
	КонецПопытки;
	
	Возврат Результат;
КонецФункции

// функция получает данные ячейки и значение
//
// В любом случае возвращаем соостветствие "Значение" и "ЭтоФормула", остальное по флагам
//
Функция EXCEL_ПолучитьЗначениеЯчейки2 (ExcelЛист, НомерСтроки, НомерКолонки) 
	Результат = EXCEL_ПолучитьЗначениеЯчейки (ExcelЛист, НомерСтроки, НомерКолонки);
	
	Если Результат = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Результат["ЗначениеЯчейки"];
КонецФункции


//
// пример использования:
//


// будем подключаться
СоответстиеЗагрузки = EXCEL_УстановитьСвязь (ТекущийФайл.ПолноеИмя);
		
Если СоответстиеЗагрузки = Неопределено тогда
	Возврат;
КонецЕсли;
		
Для каждого ТекущаяСтраница из СоответстиеЗагрузки["Листы"] Цикл
	Значение_X1Y1 = EXCEL_ПолучитьЗначениеЯчейки2 (ТекущаяСтраница, 1, 1);
КонецЦикла;

// теперь отключаемся...
EXCEL_РазорватьСвязь (СоответстиеЗагрузки);




См. также

Добавить вознаграждение
Комментарии
1. Maljaev (maljaev) 19.11.08 14:04 Сейчас в теме
Аффтар, добавь еще это к своем примерам (только код с 7.7 на 8.х переведи): http://infostart.ru/blogs/738/
Я правда не уверен, что данная проблема существует в 8.х - заодно и расскажешь как оно там.
2. Дмитрий Воробьев (vde69) 867 19.11.08 14:23 Сейчас в теме
вроде как не должно быть проблеммы,
но я не выложил и 1/10 всего модуля по работе с екселем, просто этот блог должен давать повод задуматься, а не давать готовое решение.

Если-бы я хотел выложить библиотеку, я-бы выложил в "программах" а тут именно блог, можно пообсуждать, и т.д.
3. Maljaev (maljaev) 19.11.08 14:35 Сейчас в теме
(2) Попробуй проверь плиз, и правда интересно поддерживает ли 8.х тип "Variant" или все так же как и в 7.7?
4. Дмитрий Воробьев (vde69) 867 19.11.08 15:02 Сейчас в теме
(3) 1с8 вариант для сомов не поддерживает, приходиться изголяться, типа:
м = Новый Массив();
м.Добавить("domain");
м2 = Новый COMSafeArray(м, "VT_VARIANT");

но PageSetup.Zoom показывает как тип воолеан, но менять не дало "Произошла исключительная ситуация (Microsoft Office Excel): Нельзя установить свойство Zoom класса PageSetup"
5. Maljaev (maljaev) 19.11.08 15:09 Сейчас в теме
(4) Вот про эту ошибку я и говорил. Скриптом - прокатывает!
6. Maljaev (maljaev) 19.11.08 15:11 Сейчас в теме
(4+) Да нифига он не булевый, в нете говорят что вариант он, потому и не прокатывает прямое присвоение. Булен бы прокатил с полпинка.
7. Максим (Fuego) 413 13.12.08 13:46 Сейчас в теме
(4) тип VARIANT - это STRUCT с вложенным UNION. SafeArray и так хранит элементы как тип VARIANT, а указание "VT_VARIANT" указывает, какой тип будут содержать эти элементы. Для булевских значений вместо "VT_VARIANT" нужно указать "VT_BOOL"... А ещё для всех скажу, что 1С насковзь пропитана OLE/COM. И все её переменные, которые мы описываем в коде, есть ни что иное как VARIANT. Например "Неопределено" - это VARIANT с типом VT_EMPTY, и т.д.
8. Дмитрий Кокотов (m2d3) 19.04.12 08:02 Сейчас в теме
всё в одной кучке, спасибо
9. Евгений Фамилия (internetname) 08.02.13 13:01 Сейчас в теме
Спасибо большое, пригодилось.
10. Юрий Осипов (yuraos) 844 08.02.13 13:05 Сейчас в теме
Плюс за полезный обмен опытом!

Лень великая вешь ... говорят прогрессом движет.

Одним лень читать мануал и лезут с вопросами на форум.
Другим лень на эти вопросы отвечать и они пишут статьи, чтоб "отстали".

Самое интересное все из-за лени не остаются без дела.
:)
Вот такой диалектика получается.
11. Юрий Осипов (yuraos) 844 08.02.13 13:20 Сейчас в теме
PS:
Я тоже от лени задурился и собрал во едино
функционал для работы с COM в одной подсистеме.
Там можно работать с Excel примерно так:
УзелXLS = ПланыОбмена.ОбменДаннымиCOM.НайтиПоКоду("Excel").ПолучитьОбъект();
Опции = Новый Структура("Путь",ИмяФайлаXLS);  // если имя не указать, его 1С-ка запросит в диалоге выбора файла
ExcelApp = Null;
WorkBook = Null;
УзелXLS.Connect(ExcelApp,WorkBook,Опции);
//... что-то делаем
УзелXLS.Disconnect(ExcelApp,WorkBook,Опции);


...Показать Скрыть
12. Арсений Гришаев (Pro-tone) 82 12.12.13 16:40 Сейчас в теме
Функция   EXCEL_УстановитьСвязь (ИмяФайла)Экспорт
	
	Результат = Неопределено;
	#Если Клиент Тогда
		Состояние("Идет установка связи, ждите.....");
	#КонецЕсли
	
	Попытка
		Результат = Новый Соответствие();
		
		BaseOLE = Новый COMОбъект("Excel.Application");
		Результат.Вставить("EXCEL", BaseOLE);
		
		ExcelФайл = BaseOLE.WorkBooks.Open (ИмяФайла);
		Результат.Вставить("ExcelФайл", ExcelФайл);
		                		
		МассивЛистов = Новый Массив();
		КоличествоЛистов = ExcelФайл.Sheets.Count;
		Для е = 1 по КоличествоЛистов Цикл
			МассивЛистов.Добавить(ExcelФайл.Sheets(е));			Результат.Вставить("КоличествоКолонокЛиста"+Строка(е),ExcelФайл.Sheets.Item(1).UsedRange.Columns.Count());   //Количество колонок           Результат.Вставить("КоличествоСтрокЛиста"+Строка(е),ExcelФайл.Sheets.Item(1).UsedRange.Rows.Count());      //Количество строк   
		КонецЦикла;
				
		Результат.Вставить("Листы", МассивЛистов);

	Исключение
		Результат = Неопределено;
		#Если Клиент Тогда
			Сообщить("Ошибка создания обьекта Microsoft Excel" + ОписаниеОшибки());
		#КонецЕсли
	КонецПопытки;
	
	Возврат Результат;
КонецФункции

...Показать Скрыть
13. Арсений Гришаев (Pro-tone) 82 12.12.13 16:45 Сейчас в теме
100й пылюс от меня)

Модернизирую твою функцию, замени)
В соответствие довесил подсчет кол-ва колонок и строк на листах
Пример:
СоответстиеЗагрузки["КоличествоКолонокЛиста"+Строка(НомерЛиста)] //покажет кол-во колонок листа
СоответстиеЗагрузки["КоличествоСтрокЛиста"+Строка(НомерЛиста)] //покажет кол-во строк листа

В тег CODE не оформлял, т.к. он отсебятину какую-то вставляет в текст.


Функция EXCEL_УстановитьСвязь (ИмяФайла)Экспорт

Результат = Неопределено;
#Если Клиент Тогда
Состояние("Идет установка связи, ждите.....");
#КонецЕсли

Попытка
Результат = Новый Соответствие();

BaseOLE = Новый COMОбъект("Excel.Application");
Результат.Вставить("EXCEL", BaseOLE);

ExcelФайл = BaseOLE.WorkBooks.Open (ИмяФайла);
Результат.Вставить("ExcelФайл", ExcelФайл);

МассивЛистов = Новый Массив();
КоличествоЛистов = ExcelФайл.Sheets.Count;
Для е = 1 по КоличествоЛистов Цикл
МассивЛистов.Добавить(ExcelФайл.Sheets(е));
Результат.Вставить("КоличествоКолонокЛиста"+Строка(е),ExcelФайл.Sheets.Item(1).UsedRange.Columns.Count()); //Количество колонок
Результат.Вставить("КоличествоСтрокЛиста"+Строка(е),ExcelФайл.Sheets.Item(1).UsedRange.Rows.Count()); //Количество строк

КонецЦикла;

Результат.Вставить("Листы", МассивЛистов);

Исключение
Результат = Неопределено;
#Если Клиент Тогда
Сообщить("Ошибка создания обьекта Microsoft Excel" + ОписаниеОшибки());
#КонецЕсли
КонецПопытки;

Возврат Результат;
КонецФункции
14. Роман Антонов (ronhard) 24.10.14 15:51 Сейчас в теме
(7) Fuego, Исходя из приведенной Вами информации и кода http://infostart.ru/public/57421/ получается можно сделать следующим образом:
Перем Зум;
	Зум = Ложь;
	Эксель = Новый COMОбъект("Excel.Application");
	Книга = Эксель.WorkBooks.Add();
	ПарамСтр = Эксель.ActiveSheet.PageSetup;
	ПарамСтр.Zoom = Зум;
...Показать Скрыть


Вроде работает.
15. Роман Антонов (ronhard) 24.10.14 15:56 Сейчас в теме
Кстати и
ПарамСтр.Zoom = Ложь;
тоже работает.