Работа с файлами Excel в 1С 8.3

MS Excel давно стал стандартом для работы с электронными таблицами. Поэтому весьма частая задача, с которой сталкивается 1С разработчик – это чтение файлов Excel и загрузка их в 1С. В статье рассматриваются различные способы выгрузки и загрузки из 1С в файлы Excel.

Существует несколько способов программной работы с файлами Excel из 1С. Каждый из них имеет свои преимущества и недостатки:

  • Обмен через OLE
  • Обмен через табличный документ
  • Использование COMSafeArray
  • Обмен через ADO
  • Выгрузка без программирования

Обмен через OLE

Наверно самый распространённый вариант – обмен через технологию OLE automation. Он позволяет использовать весь функционал, предоставляемый Excel, но отличается медленной скоростью работы по сравнению с другими способами.

Обмен через OLE требует наличие установленного MS Excel на компьютере, на котором будет производиться обмен данными:

  • На компьютере конечного пользователя, если обмен происходит на стороне клиента;
  • На компьютере сервера 1С:Предприятие, если обмен происходит на стороне сервера.

Чтение из Excel через OLE:

// —— ВАРИАНТ 1 ——
// Создание COM-объекта
Эксель = Новый COMОбъект(«Excel.Application»);
// Открытие книги
Книга = Эксель.Workbooks.Open(ПутьКФайлу);
// Позиционирование на нужном листе
Лист = Книга.Worksheets(1);
// Чтение значения ячейки, обычно здесь располагается цикл обхода ячеек
ЗначениеЯчейки = Лист.Cells(НомерСтроки, НомерКолонки).Value;
// Закрытие книги
Книга.Close(0);
// Закрытие Эксель и освобождение памяти
Эксель.Quit();
Эксель = 0;
 
// —— ВАРИАНТ 2 ——
// Открытие книги
Книга = ПолучитьCOMОбъект(ПутьКФайлу);
// Позиционирование на нужном листе
Лист = Книга.Worksheets(1);
// Чтение значения ячейки, обычно здесь располагается цикл обхода ячеек
ЗначениеЯчейки = Лист.Cells(НомерСтроки, НомерКолонки).Value;
// Закрытие книги
Книга.Application.Quit();

Для обхода всех заполненных строк листа Excel можно использовать следующие приемы:

// —— ВАРИАНТ 1 ——
КоличествоСтрок = Лист.Cells(1, 1).SpecialCells(11).Row;
Для НомерСтроки = 1 По КоличествоСтрок Цикл
    ЗначениеЯчейки = Лист.Cells(НомерСтроки, НомерКолонки).Value;
КонецЦикла;
// —— ВАРИАНТ 2 ——
НомерСтроки = 0;
Пока Истина Цикл
    НомерСтроки = НомерСтроки + 1;
    ЗначениеЯчейки = Лист.Cells(НомерСтроки, НомерКолонки).Value;
    Если НЕ ЗначениеЗаполнено(ЗначениеЯчейки) Тогда
        Прервать;
    КонецЕсли;
КонецЦикла;

Очень часто приходится работать с очень большими файлами Excel, и обработка путем перебора строк занимает огромное количество времени. В таких случаях удобно в одно действие загрузить всю таблицу в массив и потом работать уже непосредственно с массивом:

ВсегоКолонок = Лист.Cells(1, 1).SpecialCells(11).Column;
ВсегоСтрок = Лист.Cells(1, 1).SpecialCells(11).Row;
Область = Лист.Range(Лист.Cells(1, 1), Лист.Cells(ВсегоСтрок, ВсегоКолонок));
Данные = Область.Value.Выгрузить();

Выгрузка в Excel через OLE:

// Создание COM-объекта
Эксель = Новый COMОбъект(«Excel.Application»);
// Отключение вывода предупреждений и вопросов
Эксель.DisplayAlerts = Ложь;
// Создание новой книги
Книга = Эксель.WorkBooks.Add();
// Позиционирование на первом листе
Лист = Книга.Worksheets(1);
// Запись значения в ячейку
Лист.Cells(НомерСтроки, НомерКолонки).Value = ЗначениеЯчейки;
// Сохранение файла
Книга.SaveAs(ИмяФайла);
// Закрытие Эксель и освобождение памяти
Эксель.Quit();
Эксель = 0;

Полезные функции при работе с Excel через OLE:

Устанавливает видимость Excel при работе //0 - Excel не виден, 1 - виден.
Соединение.Visible = Видимость;
Добавление новой книги в файл Excel Книга = Соединение.WorkBooks.Add();
Сохранение книги Excel Книга.SaveAs(ИмяФайла);
Добавление нового листа к книге Лист = Книга.WorkSheets.Add();
Переименование листа Лист.Name = ИмяЛиста;
Изменение маштаба листа //"Масштаб" (от 10 до 400).
Лист.PageSetup.Zoom = Масштаб;
Изменение ориентации листа //1 - книжная, 2 - альбомная.
Лист.PageSetup.Orientation = Ориентация;
Отступы листа //Левый отступ
Лист.PageSetup.LeftMargin = Соединение.CentimetersToPoints(Сантиметры);
//Верхний отступ
Лист.PageSetup.TopMargin = Соединение.CentimetersToPoints(Сантиметры);
//Правый отступ
Лист.PageSetup.RightMargin = Соединение.CentimetersToPoints(Сантиметры);
//Нижний отступ
Лист.PageSetup.BottomMargin = Соединение.CentimetersToPoints(Сантиметры);
Обращение к ячейке чтение/запись //Прочитать значение ячейки
//Сч = Номер строки
//Сч2 = Номер колонки
Данные = Лист.Cells(Сч, Сч2).Value;

//Записать значение в ячейку
Лист.Cells(Сч, Сч2).Value Данные;
Обращение к области ячеек //В качестве параметров передаем ячейки по диогонали
Лист.Range(ЛистЭксель.Cells(1, 1),ЛистЭксель.Cells(ВсегоСтрок, ВсегоКолонок))

Часто при чтении или записи значений в Excel, ставятся
лишние пробелы в числе. Например, 1502 может быть
считано как 1 502. В дальнейшем это значение не
приводится к числу. Эту проблему можно решить заменой.

ЗначениеЯчейки = Лист.Cells(1, 3).Value;
СтрЗаменить(Строка(ЗначениеЯчейки), Символы.НПП,"");
Объединение ячеек Лист.Range(Лист.Cells(1, 1), Лист.Cells(10, 1)).Merge();
Работа с именованными ячейками в Excel Обл = Лист.Range("Имя_Ячейки_В_Excel").Select();
Обл.Value = "Присваиваем значение";
Удаление ячейки Лист.Cells(1, 3).Delete();
Удаление области ячеек Лист.Range(Лист.Cells(1, 1), Лист.Cells(10, 1)).Delete();
Обращение к строке //Сч = Номер строки
Лист.Rows(Сч);
Изменение ширины колонки Лист.Columns(НомерКолонки).ColumnWidth = Ширина;
Обращение к колонке //Сч = Номер Колонки
Лист.Cols(Сч);
Удаление Строки Лист.Rows(Сч).Delete();
Фон ячейки/области/строки/ //Фон Ячейки
Лист.Cells(1, 1).Interior.Color = ПолучитьЦветExcelRGB(10, 10, 10);
 
//Фон Области
Лист.Range(Лист.Cells(1, 1), Лист.Cells(10, 1)).Interior.Color = ПолучитьЦветExcelRGB(10, 10, 10);
 
//Фон строки
Лист.Rows(Сч).Interior.Color = ПолучитьЦветExcelRGB(10, 10, 10);
Функция переводит цвет из формата RGB в формат Excel Функция ПолучитьЦветExcelRGB(R, G, B)
    Возврат ((B * 256) + G) * 256 + R;
КонецФункции;
Управление шрифтом в ячейке/строке/области //Изменение шрифта
Лист.Cells(НомерСтроки, НомерКолонки).Font.Name = ИмяШрифта;
 
//Изменение размера шрифтв
Лист.Cells(НомерСтроки, НомерКолонки).Font.Size = РазмерШрифта;
 
//Управление жирностью шрифта
//1-жирный шрифт (bold)
//0-нормальный шрифт (normal)
Лист.Cells(НомерСтроки, НомерКолонки).Font.Bold = Жирный;
 
//Управление курсивом шрифта
//1-Курсив
//0-Нормальный
Лист.Cells(НомерСтроки, НомерКолонки).Font.Italic = Курсив;
 
//2 - Подчеркнутый шрифт
//1- нет
Лист.Cells(НомерСтроки, НомерКолонки).Font.Underline = Подчеркнутый;
Разрешает переносить по словам в ячейке //1-Переносить
Лист.Cells(1, 1).WrapText = 1;
Управление рамкой ячейки //1 - Тонкая сплошная линия
Лист.Cells(НомерСтроки, НомерКолонки).Borders.Linestyle = ТипЛинии;
Устанавливаем формат ячейки //"@" - текстовый
//"0.00" - числовой
Лист.Cells(НомерСтроки, НомерКолонки).NumberFormat = Формат;
Формула в ячейке Лист.Cells(Сч, Сч2).FormulaLocal = "=ОКРУГЛ(135,46456;0)";
Функция для получения ширины колонки Excel  &НаКлиенте
Функция ПолучитьШиринуКолнкиЭксель (ПараметрШиринаВПикселях)
    Если ПараметрШиринаВПикселях > 9 Тогда
        ШиринаВСимволах = (ПараметрШиринаВПикселях/0.75-5)/7;
    Иначе
        ШиринаВСимволах = ПараметрШиринаВПикселях/9;
    КонецЕсли;
    Возврат ШиринаВСимволах;
КонецФункции;
Лист.Columns("A").ColumnWidth = ПолучитьШиринуКолнкиЭксель (РазмерШиринаВПикселях);
Разрешить перенос слов в ячейке Лист.Cells(1, 1).WrapText = 1;
Группировки данных на листе //Развернуть все группы (строки и колонки):
Excel.ActiveSheet.Outline.ShowLevels(3, 3);
//Сернуть все группы (строки и колонки) до первого уровня:
Excel.ActiveSheet.Outline.ShowLevels(1, 1);
//Вернуть глубину дерева:
Лист.Rows(Инд).OutlineLevel;

Обмен через табличный документ

Простой способ, суть которого в том, что объект ТабличныйДокумент имеет методы:

  • Записать(<ИмяФайла>, <ТипФайлаТаблицы>) для выгрузки данных в файл.
  • Прочитать(<ИмяФайла>, <СпособЧтенияЗначений>) для загрузки данных из файла.

Внимание!

Метод Записать() доступен как на клиенте, так и на сервере. Метод Прочитать() доступен только на стороне сервера. Необходимо помнить об этом при планировании клиент-серверного взаимодействия.


Загрузка из файла в табличный документ:

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);

Здесь ПутьКФайлу – путь к загружаемому файлу Excel. СпособЧтенияЗначенийТабличногоДокумента.Значение определяет, каким образом нужно интерпретировать данные, считываемые из исходного документа. Доступны варианты:

  • Значение.
  • Текст.

Выгрузка в файл также очень проста и осуществляется всего лишь одной строкой:

ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);

Здесь ТабДок – сформированный табличный документ, ПутьКФайлу – имя файла для выгрузки, ТипФайлаТабличногоДокумента.XLSX – формат создаваемого файла. Поддерживаются следующие форматы Excel:

  • XLS95 — формат Excel 95.
  • XLS97 — формат Excel 97.
  • XLSX — формат Excel 2007.

Использование COMSafeArray

При выгрузке больших объемов данных из 1С в Excel для ускорения можно использовать объект COMSafeArray. COMSafeArray – объектная оболочка над многомерным массивом SafeArray из COM, позволяет создавать и использовать SafeArray для обмена данными между COM-объектами. Проще говоря, это массив значений, который можно использовать для обмена между приложениями по технологии OLE.

// Создание COMSafeArray
МассивКом = Новый COMSafeArray(«VT_Variant», ВсегоКолонок, ВсегоСтрок);
// Заполнение COMSafeArray
Для Стр = 0 По ВсегоСтрок  1 Цикл
    Для Кол = 0 По ВсегоКолонок  1 Цикл
        МассивКом.SetValue(Кол, Стр, Значение);
    КонецЦикла;
КонецЦикла;
// Присвоение области листа Excel значений из COMSafeArray
Лист.Range(Лист.Cells(1, 1), Лист.Cells(ВсегоСтрок, ВсегоКолонок)).Value = МассивКом;

Обмен через ADO

Данный метод позволяет работать с Excel через ODBC и имеет ряд преимуществ:

  • Не требует установки самой Excel, необходима лишь установить ODBC. Но, как правило, он уже установлен. Эта особенность позволяет работать на стороне сервера без дополнительных установок Excel.
  • Позволяет работать с таблицей Excel как с базой данных и строить к ней запросы на T-SQL. Таким образом мы можем делать отборы еще на этапе чтения данных и другие преимущества что дает Т-SQL.

Обмен через ADO заметно быстрее обмена через OLE, но при выгрузке нет возможности использовать функционал Excel для оформления ячеек, разметки страниц, задания формул и т.д.

Выгрузка через ADO:

// Создание COM-объекта для соединения
Соединение = Новый COMОбъект(«ADODB.Connection»);
// Установка строки соединения
Соединение.ConnectionString = «
|Provider=Microsoft.ACE.OLEDB.12.0;
|Data Source=» + ИмяФайла + «;
|Extended Properties=»»Excel 12.0 XML;HDR=YES»»;»;
Соединение.Open(); // Открытие соединения
// Создание COM-объекта для команды
Команда = Новый COMОбъект(«ADODB.Command»);
Команда.ActiveConnection = Соединение;
// Присвоение текста команды для создания таблицы
Команда.CommandText = «CREATE TABLE [Лист1] (Колонка1 char(255), Колонка2 date, Колонка3 int, Колонка4 float)»;
Команда.Execute(); // Выполнение команды
// Присвоение текста команды для добавления строки таблицы
Команда.CommandText = «INSERT INTO [Лист1] (Колонка1, Колонка2, Колонка3, Колонка4) values (‘абвгдеё’, ‘8/11/2017’, ‘12345’, ‘12345,6789’)»;
Команда.Execute(); // Выполнение команды
// Удаление команды и закрытие соединения
Команда = Неопределено;
Соединение.Close();
Соединение = Неопределено;

Для создания нового листа и формирования его структуры можно воспользоваться объектами ADOX.Catalog и ADOX.Table:

// Создание COM-объекта для работы с книгой
Книга = Новый COMОбъект(«ADOX.Catalog»);
Книга.ActiveConnection = Соединение;
// Создание COM-объекта для работы со структурой данных на листе
Таблица = Новый COMОбъект(«ADOX.Table»);
Таблица.Name = «Лист1»;
Таблица.Columns.Append(«Колонка1», 202);
Таблица.Columns.Append(«Колонка2», 7);
Таблица.Columns.Append(«Колонка3», 5);
Таблица.Columns.Append(«Колонка4», 5);
// Создание в книге листа с описанной структурой
Книга.Tables.Append(Таблица);
Таблица = Неопределено;
Книга = Неопределено;

В приведенном примере в методе

Таблица.Columns.Append(«Колонка1», 202);

во втором параметре указывается тип колонки. Это не обязательный параметр, но вот некоторые значения типа колонки:

  • 5 — adDouble;
  • 6 — adCurrency;
  • 7 — adDate;
  • 11 — adBoolean;
  • 202 — adVarWChar;
  • 203 — adLongVarWChar.

Чтение через ADO:

// Создание COM-объекта для соединения
Соединение = Новый COMОбъект(«ADODB.Connection»);
// Установка строки соединения
Соединение.ConnectionString = «
|Provider=Microsoft.ACE.OLEDB.12.0;
|Data Source=» + ИмяФайла + «;
|Extended Properties=»»Excel 12.0 XML;HDR=YES»»;»;
Соединение.Open(); // Открытие соединения
// Создание COM-объекта для получения выборки
Выборка = Новый COMОбъект(«ADODB.Recordset»);
ТекстЗапроса = «SELECT * FROM [Лист1$]»;
// Выполнение запроса
Выборка.Open(ТекстЗапроса, Соединение);
// Обход результата выборки
Пока НЕ Выборка.EOF() Цикл
    ЗначениеКолонки1 = Выборка.Fields.Item(«Колонка1»).Value; // Обращение по имени колонки
    ЗначениеКолонки2 = Выборка.Fields.Item(0).Value; // Обращение по индексу колонки
    Выборка.MoveNext();
КонецЦикла;
Выборка.Close();
Выборка = Неопределено;
Соединение.Close();
Соединение = Неопределено;

В строке соединения параметр HDR определяет как будет восприниматься первая строка на листе:

  • YES – первая строка воспринимается как названия колонок. К значениям можно обращаться по имени и по индексу колонки.
  • NO – первая строка воспринимается как данные. К значениям можно обращаться только по индексу колонки.

В приведенных примерах рассмотрено лишь несколько объектов ADO. Объектная модель ADO состоит из следующих объектов:

  • Connection;
  • Command;
  • Recordset;
  • Record;
  • Fields;
  • Stream;
  • Errors;
  • Parameters;
  • Properties.

Выгрузка без программирования

Если в режиме 1С Предприятия пользователь может отобразить требуемые для выгрузки данные, то, их возможно сохранить в Excel без программирования.

Для сохранения табличного документа (например, результата отчета) можно вызвать команду Сохранить или Сохранить как в главном меню.

Для сохранения данных динамических списков (например, списка номенклатуры) необходимо:

  1. Вывести данные в табличный документ при помощи команды Еще ⇒ Вывести список.
  2. Сохранить табличный документ в требуемый формат.

 

Обратный звонок