Вообще COM-объекты используют для соединения информационной базы 1С с файлом Word, Excel, Outlook или любой другой программой, поддерживающей данный интерфейс обмена данными. В этой статье рассмотрим задачу выгрузки/загрузки данных из/в MS Excel. Чтобы это осуществить воспользуемся COM-соединением и объектом Excel.Application. Для примера возьмём задачу выгрузки/загрузки данных о номенклатуре. Пример рассмотрим ниже.
COM-соединение
Что же такое COM-соединение? Component Object Model (или COM) – это технология (фирмы Microsoft) взаимодействующих компонентов, которые одновременно могут быть использованы в разных приложениях. При этом весь функционал соответствующего компонента наследуется внутрь разрабатываемого приложения. В нашем случае COM-объект Excel.Application используется внутри кода 1С для операций с файлом книги MS Excel.
Объект Excel.Application
У объекта Excel.Application существует ряд методов, которые нам могут пригодиться для реализации нижепоставленной задачи:
- ОбъектExcel.WorkBooks.Open(ИмяФайла) – Открытие книги MS Excel
- ОбъектExcel.ActiveWorkbook.Close() – Закрытие текущей книги
- ОбъектExcel.Quit() – Закрытие COM-объекта
- ОбъектExcel.Sheets(ИмяЛиста) – Получает лист книги
- ЛистExcel.Cells(НачалоСтрока, НачалоСтолбец) – Ячейка таблицы на данном листе
- ЛистExcel.Range(Ячейка1, Ячейка2) – Выделенная область
- ЯчейкаExcel.Value – Значение ячейки таблицы
- ЯчейкаExcel.Text – Текст ячейки таблицы
Постановка задачи
Итак, предположим, что в обработке 1С у нас имеется табличная часть, состоящая из следующих колонок:
- Номенклатура
- Количество
- Цена
- Сумма.
Необходимо реализовать 2 функционала (сделать на форме 2 основные кнопки):
- Выгрузка табличной части в подготовленный файл MS Excel
- Загрузка табличной части из файла.

Алгоритм выгрузки/загрузки в MS Excel
Алгоритм выгрузки следующий:
- Выгружаем табличную часть в таблицу значений
- Создаём новый COM-объект Excel.Application
- Выбираем файл, открываем файл книги MS Excel
- Переходим на заданный лист книги
- Выгружаем данные в файл
- Закрываем книгу, выходим из COM-объекта.
Алгоритм загрузки следующий:
- Создаём новый COM-объект Excel.Application
- Выбираем файл, открываем файл книги MS Excel
- Переходим на заданный лист книги
- Загружаем данные из файла в таблицу значений
- Закрываем книгу, выходим из COM-объекта
- Таблицу значений выгружаем в табличную часть.
Операция выгрузки и загрузки данных о номенклатуре происходит в заранее подготовленный шаблон MS Excel.

Пример кода 1С
Код 1С я постарался разделить на отдельные функции, чтобы, скопировав, с ними можно было работать где угодно. На форме обработки 1С были созданы 3 кнопки:
- Выгрузить
- Загрузить
- Очистить.

В итоге в реализации алгоритма получились следующие основные процедуры и функции 1С:
- ПолучитьExcel – Получает COM-объект MS Excel;
- ЗакрытьExcel – Закрывает использование COM-объекта MS Excel;
- ПолучитьЛистExcel – Получает лист книги Excel;
- ДобавитьТабличныйДокументВExcel – Добавляет табличный документ на лист Excel (нужно для выгрузки данных);
- ПрочитатьОбластьИзExcel – Читает область ячеек с листа Excel (нужно для загрузки данных);
- ШиринаЛистаExcel – Ширина листа Excel;
- ВысотаЛистаExcel – Высота листа Excel;
- ПреобразоватьТДвТЗ – Преобразует табличный документ в таблицу значений;
- ПреобразоватьТЗвТД – Преобразует таблицу значений в табличный документ;
Для начала приведу вспомогательную функцию для открытия/сохранения файла на диске:
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 | #Если Клиент Тогда
// Функция выбора файла.
//
// Параметры:
// РежимВыбора - <РежимДиалогаВыбораФайла> - Выбор каталога, открытие или сохранение файла;
// Расширение - <Строка>, <Массив> - Список расширений файла.
//
// Возвращаемое значение:
// <Строка> - Путь к выбранному файлу.
//
Функция ВыбратьФайлДокумента(РежимВыбора, Расширение = "*") Экспорт
ИмяФайла = "";
//ФорматМассив = РазобратьСтрокуВМассивПоРазделителю(Расширение);
ФорматМассив = ПреобразоватьВМассив(Расширение);
ДиалогФайла = Новый ДиалогВыбораФайла(РежимВыбора);
Если РежимВыбора = РежимДиалогаВыбораФайла.Открытие Тогда
ДиалогФайла.Заголовок = "Открыть документ";
ИначеЕсли РежимВыбора = РежимДиалогаВыбораФайла.Сохранение Тогда
ДиалогФайла.Заголовок = "Сохранить документ";
ИначеЕсли РежимВыбора = РежимДиалогаВыбораФайла.ВыборКаталога Тогда
ДиалогФайла.Заголовок = "Выбрать каталог";
КонецЕсли;
Фильтр = "";
Для Каждого ЭлементМассив Из ФорматМассив Цикл
Если ЭлементМассив = "*" Тогда
Фильтр = Фильтр + "|" + НСтр("ru = ""Все файлы""; en = ""All files""");
ИначеЕсли ВРег(ЭлементМассив) = ВРег("TXT") Тогда
Фильтр = Фильтр + "|" + НСтр("ru = ""Текстовый документ""; en = ""Text document""");
ИначеЕсли ВРег(ЭлементМассив) = ВРег("MXL") Тогда
Фильтр = Фильтр + "|" + НСтр("ru = ""Табличный документ""; en = ""Table document""");
ИначеЕсли ВРег(ЭлементМассив) = ВРег("XLS") ИЛИ ВРег(ЭлементМассив) = ВРег("XLSX") ИЛИ ВРег(ЭлементМассив) = ВРег("XLSM") Тогда
Фильтр = Фильтр + "|" + НСтр("ru = ""Табличный документ MS Excel""; en = ""Table document MS Excel""");
ИначеЕсли ВРег(ЭлементМассив) = ВРег("XML") Тогда
Фильтр = Фильтр + "|" + НСтр("ru = ""Документ XML""; en = ""Document XML""");
ИначеЕсли ВРег(ЭлементМассив) = ВРег("HTML") ИЛИ ВРег(ЭлементМассив) = ВРег("HTM") Тогда
Фильтр = Фильтр + "|" + НСтр("ru = ""HTML документ""; en = ""HTML document""");
Иначе
Фильтр = Фильтр + "|" + НСтр("ru = ""Файл " + ВРег(ЭлементМассив) + """; en = ""File " + ВРег(ЭлементМассив) + """");
КонецЕсли;
Фильтр = Фильтр + " (*." + НРег(ЭлементМассив) + ")|*." + НРег(ЭлементМассив);
КонецЦикла;
Фильтр = Сред(Фильтр, 2);
ДиалогФайла.Фильтр = Фильтр;
ДиалогФайла.МножественныйВыбор = Ложь;
Если ДиалогФайла.Выбрать() Тогда
ИмяФайла = ?(РежимВыбора = РежимДиалогаВыбораФайла.ВыборКаталога, ДиалогФайла.Каталог, ДиалогФайла.ПолноеИмяФайла);
Иначе
Текст = "ru = ""Файл не выбран!""; en = ""File(s) not selected!""";
Предупреждение(НСтр(Текст));
КонецЕсли;
Возврат ИмяФайла;
КонецФункции
#КонецЕсли |
Также в реализации алгоритма были задействованы следующие вспомогательные функции:
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 | // Преобразует в массив переменную любого типа данных.
//
// Параметры:
// Объект - Произвольный - произвольный объект данных;
// Проверка - <Булево> - Осуществление проверки на заполненное значение.
//
// Возвращаемое значение:
// <Массив> - Массив с теми же данными.
//
Функция ПреобразоватьВМассив(Объект, Проверка = Ложь) Экспорт
ОбъектМассив = Новый Массив;
Если НЕ Проверка ИЛИ ЗначениеЗаполнено(Объект) Тогда
Если ТипЗнч(Объект) = Тип("Массив") Тогда
ОбъектМассив = Объект;
ИначеЕсли ТипЗнч(Объект) = Тип("СписокЗначений") Тогда
ОбъектМассив = Объект.ВыгрузитьЗначения();
ИначеЕсли ТипЗнч(Объект) = Тип("Строка") Тогда
ОбъектМассив = РазобратьСтрокуВМассивПоРазделителю(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("Структура") Тогда
Для Каждого Элемент Из Объект Цикл
ОбъектМассив.Добавить(Элемент.Значение);
КонецЦикла;
Иначе
ОбъектМассив.Добавить(Объект);
КонецЕсли;
КонецЕсли;
Возврат ОбъектМассив;
КонецФункции; |
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 | // Разбирает строку в массив подстрок по разделителю. // При этом пробелы между подстроками не учитываются. // // Параметры: // Стр - исходная строка; // СтрРазделитель - разделитель, по умолчанию ","; // ИгнорироватьПустые - игнорировать ли пустые места между разделителями. // // Возвращаемое значение: // Массив строк // Функция РазобратьСтрокуВМассивПоРазделителю(Знач Стр, СтрРазделитель = ",", ИгнорироватьПустые = Ложь) Экспорт Результат = Новый Массив; ВхождениеРазделителя = Найти(Стр, СтрРазделитель); Пока ВхождениеРазделителя <> 0 Цикл ЧастьДоРазделителя = СокрЛП(Лев(Стр, ВхождениеРазделителя - 1)); Если НЕ (ИгнорироватьПустые И ПустаяСтрока(ЧастьДоРазделителя)) Тогда Результат.Добавить(ЧастьДоРазделителя); КонецЕсли; Стр = СокрЛП(Сред(Стр, ВхождениеРазделителя + 1)); ВхождениеРазделителя = Найти(Стр, СтрРазделитель); КонецЦикла; Если НЕ (ИгнорироватьПустые И ПустаяСтрока(Стр)) Тогда Результат.Добавить(СокрЛП(Стр)); КонецЕсли; Возврат Результат; КонецФункции; |
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 | // Создаёт новую таблицу значений с заданными колонками.
//
// Параметры:
// пКолонки - <Строка>, <Структура>, <Массив>, <СписокЗначений>, <ТаблицаЗначений> -
// Набор колонок для таблицы значений.
//
// Возвращаемое значение:
// <ТаблицаЗначений> - Созданная таблица.
//
Функция ПолучитьТаблицуВывода(пКолонки) Экспорт
ТЗ = Новый ТаблицаЗначений;
Если пКолонки <> Неопределено Тогда
Если ТипЗнч(пКолонки) = Тип("Строка") Тогда
пКолонки = РазобратьСтрокуВМассивПоРазделителю(пКолонки);
КонецЕсли;
Если ТипЗнч(пКолонки) = Тип("Структура") Тогда
Для Каждого Поле Из пКолонки Цикл
СтрокаТабл = ТЗ.Колонки.Добавить(Поле.Ключ, Поле.Значение);
КонецЦикла;
ИначеЕсли ТипЗнч(пКолонки) = Тип("СписокЗначений") Тогда
Для Каждого Поле Из пКолонки Цикл
Если Поле.Пометка Тогда
СтрокаТабл = ТЗ.Колонки.Добавить(Поле.Значение, пКолонки.ТипЗначения, Поле.Представление);
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипЗнч(пКолонки) = Тип("ТаблицаЗначений") Тогда
ЕстьНаименование = (пКолонки.Колонки.Найти("Наименование") <> Неопределено);
ЕстьТипЗначения = (пКолонки.Колонки.Найти("ТипЗначения") <> Неопределено);
ЕстьЗаголовок = (пКолонки.Колонки.Найти("Заголовок") <> Неопределено);
ЕстьШирина = (пКолонки.Колонки.Найти("Ширина") <> Неопределено);
Для Каждого Поле Из пКолонки Цикл
СтрокаТабл = ТЗ.Колонки.Добавить(?(ЕстьНаименование, Поле.Наименование, ""), ?(ЕстьТипЗначения, Поле.ТипЗначения, Новый ОписаниеТипов), ?(ЕстьЗаголовок, Поле.Заголовок, ""), ?(ЕстьШирина, Поле.Ширина, 0));
КонецЦикла;
Иначе
Для Каждого Поле Из пКолонки Цикл
СтрокаТабл = ТЗ.Колонки.Добавить(Поле);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат ТЗ;
КонецФункции; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Создаёт структуру колонок из таблицы значений. // // Параметры: // ТабЗначений - <ТаблицаЗначений> - Любая таблица. // // Возвращаемое значение: // <Структура> - Созданная таблица. // Функция ПолучитьСтруктуруКолонокИзТаблицы(ТабЗначений) Экспорт СтруктураКолонок = Новый Структура; Для Каждого ЭлементКолонка Из ТабЗначений.Колонки Цикл СтруктураКолонок.Вставить(ЭлементКолонка.Имя, ЭлементКолонка.ТипЗначения); КонецЦикла; Возврат СтруктураКолонок; КонецФункции; |
Основные функции обработки алгоритма следующие:
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 | // Получает объект файла MS Excel.
//
// Параметры:
// ИмяФайла - <Строка> - Путь к файлу XLS.
//
// Возвращаемое значение:
// <COMОбъект> - Полученный объект. Если объект не найден, то возвращается "Неопределено".
//
Функция ПолучитьExcel(ИмяФайла) Экспорт
ФайлНаДиске = Новый Файл(ИмяФайла);
Excel = Неопределено;
Если нРег(ФайлНаДиске.Расширение) = ".xls"
ИЛИ нРег(ФайлНаДиске.Расширение) = ".xlsx"
ИЛИ нРег(ФайлНаДиске.Расширение) = ".xlsm"
Тогда
Если НЕ ФайлНаДиске.Существует() Тогда
Сообщить("Файл не существует!", СтатусСообщения.Внимание);
Возврат Неопределено;
КонецЕсли;
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.WorkBooks.Open(ИмяФайла);
Исключение
Сообщить("Не удалось инициализировать Excel!", СтатусСообщения.Внимание);
Возврат Неопределено;
КонецПопытки;
КонецЕсли;
Возврат Excel;
КонецФункции; |
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 | // Закрывает файл MS Excel.
//
// Параметры:
// Excel - <COMОбъект> - Объект файла MS Excel;
// Сохранить - <Булево> - Указывает сохранять файл при закрытии или нет. По умолчанию
// пользователю предлагается выбрать это самому.
//
Процедура ЗакрытьExcel(Excel, Сохранить = Неопределено) Экспорт
Попытка
#Если Клиент Тогда
Состояние("Закрытие файла Microsoft Excel...");
#КонецЕсли
Если Сохранить = Неопределено Тогда
Excel.ActiveWorkbook.Close();
Иначе
Excel.ActiveWorkbook.Close(Сохранить);
КонецЕсли;
Excel.Quit();
Исключение
Сообщить("Ошибка закрытия Excel!", СтатусСообщения.Внимание);
КонецПопытки;
Excel = Неопределено;
КонецПроцедуры; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Получает лист из файла книги MS Excel.
//
// Параметры:
// Excel - <COMОбъект> - Объект файла MS Excel;
// ИмяЛиста - <Строка> - Имя листа книги MS Excel.
//
// Возвращаемое значение:
// <COMОбъект> - Полученный лист. Если объект не найден, то возвращается "Неопределено".
//
Функция ПолучитьЛистExcel(Excel, ИмяЛиста) Экспорт
Попытка
ExcelЛист = Excel.Sheets(ИмяЛиста);
Исключение
Сообщить("Не удалось прочитать лист Excel!", СтатусСообщения.Внимание);
Возврат Неопределено;
КонецПопытки;
Возврат ExcelЛист;
КонецФункции; |
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 | // Записывает данные из табличного документа в файл MS Excel.
//
// Параметры:
// ЛистExcel - <COMОбъект> - Лист из файла MS Excel;
// Таблица - <ТабличныйДокумент> - Документ, по порядку следования колонок и строк
// соответствующий листу файла MS Excel;
// Шапка - <Число> - Количество первых строк для шапки в файле MS Excel;
// СписокСтолбцов - <Строка>, <Массив> - Список номеров столбцов, которые будут выгружены
// в файл MS Excel;
// СписокСтрокЗапрета - <Строка>, <Массив> - Список номеров строк, которые не должны
// выгружаться в файл MS Excel. Если этот параметр не задан, то выгружаются все строки;
// ПроверятьЗначения - <Булево> - Определяет будут ли проверяться ячейки табличного
// документа на содержание в них значения, а не текстовое представление этого значения.
// По умолчанию этот параметр "Ложь".
//
Процедура ДобавитьТабличныйДокументВExcel(ЛистExcel, Таблица, Шапка, СписокСтолбцов, СписокСтрокЗапрета = Неопределено, ПроверятьЗначения = Ложь) Экспорт
Если ТипЗнч(СписокСтолбцов) = Тип("Строка") Тогда
СписокСтолбцов = РазобратьСтрокуВМассивПоРазделителю(СписокСтолбцов);
КонецЕсли;
Если ТипЗнч(СписокСтрокЗапрета) = Тип("Строка") Тогда
СписокСтрокЗапрета = РазобратьСтрокуВМассивПоРазделителю(СписокСтрокЗапрета);
КонецЕсли;
ЕстьМассив = (СписокСтрокЗапрета = Неопределено);
Если ЕстьМассив Тогда
Попытка
МассивCOM = Новый COMSafeArray("VT_VARIANT", 1, Таблица.ВысотаТаблицы - Шапка);
Исключение
ЕстьМассив = Ложь;
КонецПопытки;
КонецЕсли;
Для Каждого НомерСтолбца Из СписокСтолбцов Цикл
Для НомерСтроки = Шапка+1 По Таблица.ВысотаТаблицы Цикл
Если СписокСтрокЗапрета = Неопределено
ИЛИ (СписокСтрокЗапрета.Найти(Строка(НомерСтроки)) = Неопределено И СписокСтрокЗапрета.Найти(Число(НомерСтроки)) = Неопределено)
Тогда
Область = Таблица.Область(НомерСтроки, Число(НомерСтолбца));
Значение = ?(ПроверятьЗначения И Область.СодержитЗначение, Область.Значение, Область.Текст);
Если ЕстьМассив Тогда
МассивCOM.SetValue(0, НомерСтроки-Шапка-1, Значение);
Иначе
ЛистExcel.Cells(НомерСтроки, Число(НомерСтолбца)).Value = Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ЕстьМассив Тогда
ЛистExcel.Range(ЛистExcel.Cells(Шапка+1, Число(НомерСтолбца)), ЛистExcel.Cells(Таблица.ВысотаТаблицы, Число(НомерСтолбца))).Value = МассивCOM;
КонецЕсли;
КонецЦикла;
КонецПроцедуры; |
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 | // Читает область ячеек из MS Excel в табличный документ.
//
// Параметры:
// ЛистExcel - <COMОбъект> - Лист из файла MS Excel;
// ТабДок - <ТабличныйДокумент> - Исходный табличный документ, поле табличного
// документа или таблица значений. Если этот параметр не задан, то создаётся
// новый табличный документ;
// НачалоСтрока - <Число> - Начальная строка в файле MS Excel;
// НачалоСтолбец - <Число> - Начальный столбец в файле MS Excel;
// КонецСтрока - <Число> - Конечная строка в файле MS Excel;
// КонецСтолбец - <Число> - Конечный столбец в файле MS Excel.
//
// Возвращаемое значение:
// <ТабличныйДокумент> - Возвращает прочитанный из области в MS Excel табличный
// документ, который передавался в эту функцию параметром "ТабДок".
//
Функция ПрочитатьОбластьИзExcel(ЛистExcel, ТабДок = Неопределено, НачалоСтрока, НачалоСтолбец, КонецСтрока, КонецСтолбец) Экспорт
Если ТабДок = Неопределено Тогда
ТабДок = Новый ТабличныйДокумент;
КонецЕсли;
Попытка
МассивCOM = Новый COMSafeArray("VT_VARIANT", КонецСтолбец - НачалоСтолбец + 1, КонецСтрока - НачалоСтрока + 1);
ЕстьМассив = Истина;
Исключение
ЕстьМассив = Ложь;
КонецПопытки;
Если ЕстьМассив Тогда
МассивCOM = ЛистExcel.Range(ЛистExcel.Cells(НачалоСтрока, НачалоСтолбец), ЛистExcel.Cells(КонецСтрока, КонецСтолбец)).Value;
Для ИндексКолонка = НачалоСтолбец По КонецСтолбец Цикл
Для ИндексСтрока = НачалоСтрока По КонецСтрока Цикл
Значение = МассивCOM.GetValue(ИндексКолонка - НачалоСтолбец + 1, ИндексСтрока - НачалоСтрока + 1);
ТабДок.Область(ИндексСтрока, ИндексКолонка).СодержитЗначение = Истина;
ТабДок.Область(ИндексСтрока, ИндексКолонка).Значение = Значение;
КонецЦикла;
КонецЦикла;
Иначе
Для ИндексКолонка = НачалоСтолбец По КонецСтолбец Цикл
Для ИндексСтрока = НачалоСтрока По КонецСтрока Цикл
Значение = ЛистExcel.Cells(ИндексСтрока, ИндексКолонка).Value;
ТабДок.Область(ИндексСтрока, ИндексКолонка).СодержитЗначение = Истина;
ТабДок.Область(ИндексСтрока, ИндексКолонка).Значение = Значение;
КонецЦикла;
КонецЦикла;
КонецЕсли;
Возврат ТабДок;
КонецФункции; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Определяет ширину листа MS Excel. // // Параметры: // ЛистExcel - <COMОбъект> - Лист из файла MS Excel. // // Возвращаемое значение: // <Число> - Количество столбцов в таблице. // Функция ШиринаЛистаExcel(ЛистExcel) Экспорт ЕстьЗащита = ЛистExcel.ProtectContents; Возврат ?(ЕстьЗащита, ЛистExcel.UsedRange.Columns.Count, ЛистExcel.Cells.SpecialCells(11).Column); КонецФункции; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Определяет высоту листа MS Excel. // // Параметры: // ЛистExcel - <COMОбъект> - Лист из файла MS Excel. // // Возвращаемое значение: // <Число> - Количество строк в таблице. // Функция ВысотаЛистаExcel(ЛистExcel) Экспорт ЕстьЗащита = ЛистExcel.ProtectContents; Возврат ?(ЕстьЗащита, ЛистExcel.UsedRange.Rows.Count, ЛистExcel.Cells.SpecialCells(11).Row); КонецФункции; |
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 | // Преобразовать табличный документ в таблицу значений.
//
// Параметры:
// ТабДок - <ТабличныйДокумент> - Исходный табличный документ;
// СтруктураКолонок - <Структура>, <ТаблицаЗначений> - Структура колонок;
// НачалоСтрока - <Число> - Строка начала области;
// НачалоСтолбец - <Число> - Столбец начала области;
// КонецСтрока - <Число> - Строка конца области;
// КонецСтолбец - <Число> - Столбец конца области.
//
// Возвращаемое значение:
// <ТаблицаЗначений> - Полученная таблица значений.
//
Функция ПреобразоватьТДвТЗ(ТабДок, СтруктураКолонок, Знач НачалоСтрока = Неопределено, Знач НачалоСтолбец = Неопределено, Знач КонецСтрока = Неопределено, Знач КонецСтолбец = Неопределено) Экспорт
// Определение габаритов таблицы
Если НачалоСтрока = Неопределено И НачалоСтолбец = Неопределено Тогда
НачалоСтрока = 1;
НачалоСтолбец = 1;
КонецЕсли;
Если НачалоСтрока = Неопределено Тогда
НачалоСтрока = 1;
Пока НЕ ТабДок.Область(НачалоСтрока, НачалоСтолбец).СодержитЗначение
И НачалоСтрока < ТабДок.ВысотаТаблицы
Цикл
НачалоСтрока = НачалоСтрока + 1;
КонецЦикла;
ИначеЕсли НачалоСтолбец = Неопределено Тогда
НачалоСтолбец = 1;
Пока НЕ ТабДок.Область(НачалоСтрока, НачалоСтолбец).СодержитЗначение
И НачалоСтолбец < ТабДок.ШиринаТаблицы
Цикл
НачалоСтолбец = НачалоСтолбец + 1;
КонецЦикла;
КонецЕсли;
КонецСтрока = ?(КонецСтрока = Неопределено, ТабДок.ВысотаТаблицы, КонецСтрока);
КонецСтолбец = ?(КонецСтолбец = Неопределено, ТабДок.ШиринаТаблицы, КонецСтолбец);
// Преобразование
ЭтоТаблица = (ТипЗнч(СтруктураКолонок) = Тип("ТаблицаЗначений"));
ТабЗначений = ПолучитьТаблицуВывода(СтруктураКолонок);
Для ИндексСтроки = НачалоСтрока По КонецСтрока Цикл
СтрокаТЗ = ТабЗначений.Добавить();
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из СтруктураКолонок Цикл
НаименованиеКолонки = ?(ЭтоТаблица, Колонка.Наименование, Колонка.Ключ);
пИндексКолонки = ?(ЭтоТаблица, Колонка.СтолбецОтчёт, ИндексКолонки);
Если ТабДок.Область(ИндексСтроки, пИндексКолонки).СодержитЗначение Тогда
СтрокаТЗ[НаименованиеКолонки] = ТабДок.Область(ИндексСтроки, пИндексКолонки).Значение;
Иначе
СтрокаТЗ[НаименованиеКолонки] = ТабДок.Область(ИндексСтроки, пИндексКолонки).Текст;
КонецЕсли;
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
КонецЦикла;
Возврат ТабЗначений;
КонецФункции; |
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 | // Преобразовать таблицу значений в табличный документ. // // Параметры: // ТабЗначений - <ТаблицаЗначений> - Исходная таблица значений; // ТабДок - <ТабличныйДокумент> - Полученный табличный документ. Если параметр не задан, // то документ создаётся заново и возвращается функцией; // НачалоСтрока - <Число> - Строка начала области; // НачалоСтолбец - <Число> - Столбец начала области; // ВыводитьЗаголовки - <Булево> - Определяет выводить ли имена колонок или нет. // // Возвращаемое значение: // <ТабличныйДокумент> - Полученный табличный документ (возвращает параметр "ТабДок"). // Функция ПреобразоватьТЗвТД(ТабЗначений, ТабДок = Неопределено, Знач НачалоСтрока = Неопределено, Знач НачалоСтолбец = Неопределено, ВыводитьЗаголовки = Ложь) Экспорт Если ТабДок = Неопределено Тогда ТабДок = Новый ТабличныйДокумент; КонецЕсли; // Определение габаритов таблицы НачалоСтрока = ?(НачалоСтрока = Неопределено, 1, НачалоСтрока); НачалоСтолбец = ?(НачалоСтолбец = Неопределено, 1, НачалоСтолбец); // Преобразование ИндексСтроки = НачалоСтрока; Если ВыводитьЗаголовки Тогда ИндексКолонки = НачалоСтолбец; Для Каждого Колонка Из ТабЗначений.Колонки Цикл ТабДок.Область(ИндексСтроки, ИндексКолонки).Текст = ?(ПустаяСтрока(Колонка.Заголовок), Колонка.Имя, Колонка.Заголовок); ИндексКолонки = ИндексКолонки + 1; КонецЦикла; ИндексСтроки = ИндексСтроки + 1; КонецЕсли; Для Каждого Элемент Из ТабЗначений Цикл ИндексКолонки = НачалоСтолбец; Для Каждого Колонка Из ТабЗначений.Колонки Цикл ТабДок.Область(ИндексСтроки, ИндексКолонки).СодержитЗначение = Истина; ТабДок.Область(ИндексСтроки, ИндексКолонки).ТипЗначения = Новый ОписаниеТипов(Колонка.ТипЗначения); ТабДок.Область(ИндексСтроки, ИндексКолонки).Значение = Элемент[Колонка.Имя]; ИндексКолонки = ИндексКолонки + 1; КонецЦикла; ИндексСтроки = ИндексСтроки + 1; КонецЦикла; Возврат ТабДок; КонецФункции; |
В реализации алгоритма был дополнительно использован объект COMSafeArray с типом VT_VARIANT. Этот COM-объект выступает в качестве двумерного массива, в котором удобно хранить значения ячеек. Также использование данного объекта повышает быстродействие операций чтения/записи для ячеек таблицы.
Целиком получившуюся обработку 1С, а также шаблон для загрузки/выгрузки можно скачать по ссылке ниже.
Указанные здесь процедуры и функции я постарался сделать универсальными. Они могут быть применены для широкого круга прикладных задач.


Вчерашний день всё это, надо на управляемых формах писать.
Заходи к нам на forum330.com, научим.
Интерфейс Такси я имел ввиду.
А никто не мешает всё это дело адаптировать под управляемые формы и интерфейс такси. Изменения в коде будут минимальны.
Полезная статья, от себя хотел заметить, что при обработке большого объема данных что обращение к свойству value затратно по ресурсам. Часто при необходимости ускорить загрузку если заранее знаем, что нас интересует текстовое представление данных сразу используем text
Да, действительно иногда стоит использовать поле «Text»