Com на примере excel

Содержание

  1. Обработка COM-объекта на клиенте: Загрузка из Excel в 1С
  2. Com на примере excel
  3. Параграф 5. Вывод информации в ячейки Excel
  4. 5.1. Вывод без форматирования
  5. 5.2. Форматированный вывод
  6. 5.3. Вставка формул
  7. Параграф 6. Защита листа и книги документа Excel
  8. Параграф 7. Чтение информации из ячеек Excel
  9. Параграф 8. Рисуем таблички
  10. Параграф 9. Создание диаграмм
  11. 8.1. Пошаговое создание диаграмм
  12. 9.2. Использование метода ChartWizard для создания диаграмм
  13. Параграф 10. Обработка событий сервера Excel
  14. Параграф 11. Об особенности использования метода Activate в VS 2005/2008
  15. Параграф 12. Автозаполнение или работа с диапазонами
  16. Параграф 13. Некоторые возможности по управлению параметрами Excel
  17. Заключение. О богатстве возможностей

Рассмотрим пример обработки COM-объекта на Клиенте на примере загрузки из файла xls.

В случаях, когда на сервере не установлен Excel или когда сервер 1С:Предприятие 64-х битный, а объем загружаемых данных небольшой, данные файла xls можно обработать на Клиенте и передать для дальнейшей обработки на Сервер. Рассмотрим на примере.

Внешняя обработка с табличной частью ТабЧасть, СотрудникСтр — строка для заполнения из xls файла на Клиенте, Сотрудник — СправочникСсылка.СотрудникиОрганизаций для заполнения из значения СотрудникСтр на Сервере. В файле xls в колонке 1 — наименования сотрудников, в колонке 2 — суммы, данные по сотрудникам начинаются с 7-й строки файла.

Процедуры модуля формы обработки:

Эту статью хорошо дополняют

UI в 1С: как быстро создать интерфейс сервисом 1C Maker

Простой и доступный инструмент для оперативного решения вопросов по визуализации ТЗ

1С Hard Skills / 8.11.2022

Производительный режим RLS в 1С

Преимущества и недостатки стандартного и производительного режима RLS

1С Hard Skills / 13.07.2022

Как работают виртуальные таблицы Остатки, Обороты, ОстаткиИОбороты, особенности применения в СКД. Особенности объекта СтандартныйПериод

Источник

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

Для демонстрации некоторых возможностей функции, создадим в любом текстовом редакторе простой текстовый файл «a.txt», в котором столбцы разделены символом табуляции — Tab (Рис.3).

Рис.3 Текстовый файл для импорта

Выполним следующий код:

Результат выполнения фрагмента кода показан на Рис.4.

Рис.4. Импортированный текстовый файл

С этим примером можно поэкспериментировать, меняя системные установки и заданные в программе разделители и меняя формат ячеек с числовой информацией.

Параграф 5. Вывод информации в ячейки Excel

5.1. Вывод без форматирования

Для примеров данного параграфа будем использовать файл «C:a.xls», созданный в предыдущем пункте.

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

Обратим внимание на разницу задания всех и рабочих листов книги.

Аналогичного определения для ячеек и ячейки мы задать не можем, так как отдельно данные объекты как самостоятельные в C# отсутствуют, а есть понятие области выделенных ячеек, которая может включать одну или более ячеек, с которыми можно выполнять действия. Поэтому для ячеек, с которыми выполняется действие, введем следующее определение:

Для выделения используется метод get_Range, который позволяет выделить группу ячеек через задание угловых ячеек диапазона, и есть возможность обратиться непосредственно к свойствам Rows и Cells — в любом случае выделенным будет диапазон ячеек.

Еще один способ определения выбранных ячеек — использование метода get_Offset(x,y) объекта Range, возвращающего объект Range, отстоящий от заданной ячейки на заданное количество строк и столбцов, считая от левого верхнего угла. Это позволяет работать с ячейками, позиция которых заданы относительно выбранной ячейки или группы ячеек.

Возможности объединения ячеек гораздо богаче — можно использовать объединения областей, группу областей, определение границ выделенных ячеек и.т.п., однако, для большинства практических задач вполне достаточно перечисленных выше методов.

Выделенные ячейки далее могут быть объединены и с ними действия могут выполняться как с одной ячейкой. Для этого используется метод Merge:

На данном этапе мы уже использовали основные объекты иерархической структуры объектов Excel. Следует также отметить и еще одну особенность группы свойств Excel.Application. Как только мы получили ссылку на конкретный объект (книгу, лист, группу ячеек, диаграмму) их можно сделать активными, применив к ним метод Activate(). С этого момента они доступны через соответствующие свойства ActiveWorkbook, ActiveSheet, ActiveChart, ActiveCell. Кроме того, при выполнении действий с конкретным объектом, он автоматически становится активным и, действия с ним могут далее выполняться с использованием перечисленных свойств.

Точно также можно использовать и свойство Excel.Application Selection. То есть, объект может быть определен как селектированный и, далее, для ссылки на объект использоваться свойство Selection.

В следующем примере объединяется группа ячеек в одну без ссылки на выделенный объект.

Хотя это и заманчиво, чтобы работать с текущим селективным выбором как средством изменения свойств и поведения объекта, но лучше, все-таки, избегать этого. Причина — селективный выбор может быть легко изменен и во время выполнения приложения, например, кликом мышки в пределах документа, что при большом объеме вывода на 100% приведет к ошибке.

Рассмотрим пример различных вариантов вывода в ячейки Excel, на различные страницы рабочей книги:

Рис.5. Результаты выполнения фрагмента кода

Результаты выполнения фрагмента кода показаны на Рис.5.

Заметим, что в C# требуется считывать и присваивать значения свойству Value2, а не Value объекта Range, так как свойство Value содержит параметр. C# не поддерживает свойства с параметрами (за исключением индексных свойств).

Если в приведенном выше примере для вывода на лист 1 выбрать не одну, а сразу несколько ячеек, то результат можно видеть на Рис.5.1. (фрагмент слева).

Однако, как и в приложении Excel, можно объединить ячейки программно, задать выравнивание и получить результат, как на Рис.5.1 (вторай слева фрагмент).

Рис. 5.1 Результаты выполнения примера c объединением ячеек

5.2. Форматированный вывод

При выводе информации часто бывает необходимо изменить формат ячейки, например, задать числовой формат, это можно сделать следующим образом:

Результат будет зависеть от системных установок Windows (Пуск|Настройка|Панель управления|Язык и стандарты) и, для данного примера, результат может быть как на Рис.5.1. (третий слева фрагмент).

Для формата даты и установки общего формата:

Результат выполнения Рис.5.1. (фрагмент справа).

И последнее — возврат к общему формату.

Приведенный ниже пример форматирования текста в ячейках добавлен в качестве ответа на вопрос, поступивший автору 20.01.2009г.

Попробуем выполнить форматирование, показанное на Рис.6.

Рис.6. Пример форматированного вывода

Макрос, реализующий данное форматирование, имеет вид:

Его перевод на C#, будет выглядеть примерно так:

5.3. Вставка формул

Параграф 6. Защита листа и книги документа Excel

Материал прислан Андреем Ковалевым и отредактирован автором.

Для защиты листа документа или книги Excel необходимо установить пароль. В качестве пароля используется любая переменная тира string.

Пароль задавать необязательно — string s=string.Emptu; однако, если не задать пароль, любой пользователь сможет снять защиту с листа и изменить защищенные элементы.

Второй параметр: true, означает защиту структуры (запрет перемещения, удаления, скрытия, показа или переименования, а также вставки новых листов).

Третий параметр: true, означает защиту окна (блокировка окна для восстановления размера и расположения при каждом открытии книги).

Соответственно для снятия защиты книги используем:

Функция Protect определена в Microsoft.Office.Interop.Excel.dll как:

Множество параметров функции, начиная со второго, означают:

DrawingObjects — защита фигур;

Contents — защита содержимого заблокированных ячеек;

Scenarios — защита скриптов;

userInterfaceOnly — защита пользовательского интерфейса, но не макросов. Если этот аргумент не указан, защита применяется как к макросам, так и к пользовательскому интерфейсу.

AllowFormattingCells — позволяет форматирование любой ячейки защищенного рабочего листа.

AllowFormattingRows — позволяет форматирование любой строки защищенного рабочего листа.

AllowFormattingColumns — позволяет форматирование любого столбца защищенного рабочего листа.

AllowInsertingColumns — позволяет вставку столбцов;

AllowInsertingRows — позволяет вставку строк;

AllowInsertingHyperlinks — позволяет вставку гиперссылок;

AllowDeletingColumns — позволяет удаление столбцов;

AllowDeletingRows — позволяет удаление строк;

AllowSorting — разрешает сортировку;

AllowFiltering — разрешает использовать автофильтры;

allowUsingPivotTables разрешает использование отчетов сводной таблицы.

Для снятия защиты используем:

Параграф 7. Чтение информации из ячеек Excel

Чтение информации из ячеек Excel во многом аналогично выводу (см. выше). На выбранном листе необходимо в выбранной книге выбрать одну ячейку или объединенную группу ячеек (метод get_Range или преобразование к Excel.Range)- после чего достаточно преобразовать значения в выделенных ячейках к нужному типу данных.

Создадим в Excel новую книгу, на первом листе запишем соответственно:

Сохраним документ с именем a1.xls в корне диска C.

Запишем и выполним следующий код:

Код не требует пояснений — в заглавии приложения после выполнения будет выведено:

Параграф 8. Рисуем таблички

Чтобы нарисовать табличку в Excel надо научиться рисовать рамки вокруг выбранной ячейки или объединенной группы ячеек.

Шаги рисования рамки будут следующие:

Выбрать ячейку или группу ячеек на листе документа.

Определяем цвет линий обводки. Цвет может быть выбран как один из 56 цветов цветовой палитры Excel и, поэтому, он задается через цветовой индекс (например, excelcells.Borders.ColorIndex=3; — красный)
Некоторые значения ColorIndex 1 — белый, 2 — черный, 3 — красный, 4 — зеленый, 6 — желтый, 41 — синий и т.д.

Выбрать стиль линии (Excel.XlLineStyle.xlContinuous). Стиль линии может быть одним из следующих: xlContinuous, xlDash, xlDashDot, xlDashDotot, xlDot, xlDouble, xlSlantDashDot, xlLineStyleNone.

Задать толщину линии (Excel.XlBorderWeight.lHairline). Толщина линии может быть одной из следующих: lHairline, xlMedium, xlThick, xlThin.

Можно рисовать линии по любой границе ячейки и не по границе ячейки, для чего необходима задать расположение линии — вместо excelcells.Borders задать excelcells.Borders[направление], где направление может быть одним из следующих: Excel.XlBordersIndex.xlDiagonalDown, Excel.XlBordersIndex.xlDiagonalxlDiagonalUp, Excel.XlBordersIndex.xlDiagonalUp, Excel.XlBordersIndex.xlEdgeBottom, Excel.XlBordersIndex.xlEdgeLeft, Excel.XlBordersIndex.xlEdgeRight, Excel.XlBordersIndex.xlEdgeTop, Excel.XlBordersIndex.xlInsideHorizontal, Excel.XlBordersIndex.xlInsideVertical.

Следующий пример демонстрирует выполнение обводки вокруг ячеек (Рис.7. слева), и, тем самым, при использовании для некоторой группы объединенных ячеек, показывает принцип рисования табличек.

Рис.7. Создание рамок вокруг ячеек и выполнение заливки

Добавим две строчки к коду предыдущего примера и можем выполнить заливку ячеек (Рис.7. справа).

Параграф 9. Создание диаграмм

Для того, чтобы создать диаграмму, она должна быть привязана к конкретным ячейкам с цифровой информацией, поэтому откроем наш файл C:a.xls и нарисуем в нем табличку, показанную на Рис.8. (у кого есть время — может выполнить это программно — в предыдущих параграфах есть достаточно материала, чтобы сделать это).

Рис.8. Табличка для диаграммы

8.1. Пошаговое создание диаграмм

Приведенный ниже пример может показаться громоздким, и не всегда нужно будет пройти все шаги, которые требуются для создания диаграмм, и, конечно, всегда может потребоваться еще что-то в смысле дополнительных усовершенствований стилей, надписей и т.п. Однако в примере есть все, чтобы сразу, напрямую используя приведенные ниже коды, можно было использовать в приложении связанные с таблицами диаграммы. Путь создания тоже не бесспорный и ниже приведен еще один пример, как можно вставить диаграмму на лист Excel, но отличие обоих путей не существенны, а после того как диаграмма вставлена, путь ее изменения может быть только таким, как показано в этом примере.

Некоторые общие замечания по коду:

Все глобальные объявления для примера описаны в предыдущих параграфах, здесь мы только их напомним:

Пример оперирует с данными таблицы (Рис.8), в которой специально каждая цифра была размещена в двух ячейках. Это позволило показать способ удаления лишних и пустых серий линий диаграммы.

В примере сначала диаграмма размещается на отдельном листе, а затем переносится на лист, в котором размещена таблица для диаграммы — это позволит нам на практике использовать один и тот же код для различного размещения диаграмм.

Код испытан в решении, описанном в начале раздела. Как тип диаграммы можно задать один из предопределенных: xlArea, xlBar, xlColumn, xlLine, xlPie, xlRadar, xlXYScatter, xlCombination, xl3DArea, xl3DBar, xl3DColumn, xl3DLine, xl3DPie, xl3DSurface, xlDoughnut, xlDefaultAutoFormat.

Рис.9. Диаграммы на отдельном листе

Рис.10. Диаграммы на листе 1

Есть возможность поместить диаграмму сразу на выбранном листе. Но, в этом случае, нельзя использовать метод ActiveChart и, поэтому, предыдущий код незначительно изменится. В примере комментарии даны в строках, имеющих принципиальное отличие от кода предыдущего примера.

Код формирует туже диаграмму (Рис.10.), что и предыдущий пример.

9.2. Использование метода ChartWizard для создания диаграмм

Метод свойства Chart объекта типа ChartsObject имеет достаточно много параметров, большинство из которых, как всегда, могут не указываться (Type.Missing), однако чем больше их будет указано — тем меньше далее потребуется писать кода, аналогичного коду предыдущего примера. Поэтому рассмотрим параметры метода:

Немного изменим код предыдущего примера для построения диаграммы с использованием ChartWizard.

Рис.11. Диаграмма, построенная с использованием ChartWizard

Код может показаться проще, но как видно из Рис.11., метод реализует далеко не все возможности и вновь придется вернуться к методам, которые мы использовали выше.

Параграф 10. Обработка событий сервера Excel

События также необходимы для создания функционального приложения для работы с Excel как и доступ к свойствам и методам. Если рассматривать использование свойств и методов, предоставляемых интерфейсом COM объекта, как прямую связь по управлению сервером, то события обеспечивают обратную связь. Благодаря наличию событий, приложение может обеспечить программную функциональность для отклика на происходящее в приложении.

Объекты Excel, также как и любой контрол C#, имеют свои события и программист, как и для контрола, может создать обработчик для любого из событий. Однако, у нас нет визуального компонента Excel и нельзя двойным кликом мышки в окошечке напротив события в окне Properties на вкладке Events создать обработчик. Можно попробовать сделать это вручную. Вспомним, как мы это делали, например, в параграфе «Присоединение меню для формы» в первом разделе. Но, при этом, возникает вопрос — где взять передаваемые в приложения параметры событий?

И сами события, и параметры есть в проекте решения, а изложенное ниже — методика создания обработчика событий для серверов автоматизации.

Для создания обработчика событий необходимо:

1. Уяснить на какое событие, и для какого объекта мы хотим получить отклик (хотим отреагировать).

Основные события объектов Excel:

a.) связанные с поведением объектов на листе
— SheetActivate (произошла активизация листа);
— SheetBeforeDoubleClick (выполнен двойной клик на листе и после этого события ожидается какая либо реакция сервера — выполнение обработчика по умолчанию);
— SheetBeforeRightClick (выполнен правый клик на листе и после этого события ожидается какая либо реакция сервера — выполнение обработчика по умолчанию);
— SheetCalculate (выполнен пересчет формул на листе);
— SheetChange (смена выбранной ячейки на листе); SheetDeactivate (лист потерял фокус); SheetFollowHyperlink (пользователь ушел по гиперссылке); SheetSelectionChange (изменилось выделение на листе).

b.) связанные с поведением окна
— WindowActivate (произошла активизация окна если Excel на данный момент был активен);
— WindowDeactivate (окно потеряло фокус);
— WindowResize (изменился размер окна);

c.) связанные с управлением рабочей книгой — NewWorkbook (создана новая рабочая книга);
— WorkbookActivate (книга, один из ее листов, получили фокус);
— WorkbookAddinInstall (выполняется инсталляция не установленного компонента);
— WorkbookAddinUninstall (выполняется деинсталляция установленного компонента);
— WorkbookBeforeClose (после этого события ожидается закрытие книги — выполнение обработчика по умолчанию);
— WorkbookBeforePrint (после этого события ожидается печать листа — выполнение обработчика по умолчанию);
— WorkbookBeforeSave (после этого события ожидается сохранение книги — выполнение обработчика по умолчанию);
— WorkbookDeactivate (книга потеряла фокус);
— WorkbookNewSheet (в книгу добавлен лист);
— WorkbookOpen (открыта рабочая книга).

a.) все события объекта Application для пункта a, связанные с поведением объектов на листе. Генерируются только для листов данной рабочей книги.

b.) все события объекта Application для пункта b. Генерируются только для листов данной рабочей книги.

c.) связанные с управлением рабочей книгой — Activate (книга, один из ее листов, получили фокус);
— BeforeClose (после этого события ожидается закрытие книги — выполнение обработчика по умолчанию);
— BeforePrint (после этого события ожидается печать листа — выполнение обработчика по умолчанию);
— BeforeSave (после этого события ожидается сохранение книги — выполнение обработчика по умолчанию);
— Deactivate (книга потеряла фокус);
— NewSheet (в книгу добавлен лист);
— Open (открыта рабочая книга).

a) связанные с поведением объектов на листе
— Activate (произошла активизация листа);
— BeforeDoubleClick (выполнен двойной клик на листе и после этого события ожидается какая либо реакция сервера — выполнение обработчика по умолчанию);
— BeforeRightClick (выполнен правый клик на листе и после этого события ожидается какая либо реакция сервера — выполнение обработчика по умолчанию);
— Calculate (выполнен пересчет формул на листе);
— Change (смена выбранной ячейки на листе); SheetDeactivate (лист потерял фокус); SheetFollowHyperlink (пользователь ушел по гиперссылке); SheetSelectionChange (изменилось выделение на листе).

2. Инициализируем объект, для которого необходимо создать обработчик, например:

3. Находим (поставив точку после excelappworkbook . ) в списке отображенных объектов, свойств, методов и событий требуемое событие и добавляем его к объекту, например:

4. Поставив к полученной в пункте 3 строки знак += к полученной в пункте 3 строки, копируем (нажатием Tab) высвеченную подсказку в строку кода и получим:

Обработчик события создан и добавлен к объекту. excelappworkbook_SheetActivate — это имя функции обратного вызова для нашего обработчика. Осталось записать код функции обработчика и определить параметры функции.

5. Определение параметров функции кода обработчика для выбранного события.

Для определения метода необходимо (Рис.12.) в окне Solutation Explorer открыть узел Reference и двойным кликом мышки по узлу Microsoft.Office.Interop.Excel вызвать окно Object Browser. В окне Object Browser открыть узлы Microsoft.Office.Interop.Excel, и в последней открытой закладке найти узел списка событий. Выбрав узел требуемого списка событий, кликаем по нему мышкой — в правой части окна появляется список доступных событий. Выбираем требуемое событие и кликаем по нему мышкой — внизу окна появляется функция метода. Копируем из нее параметры функции: new void SheetActivate ( Object Sh ).

PS: Еще проще, в контекстном меню делегата WorkbookEvents_SheetActivateEventHandler выбрать пункт Go To Difination и посмотреть параметры определенные в dll Microsoft.Office.Interop.Excel:

Рис.12. Определение параметров функции кода обработчика

Пишем код функции для события:

6. Осталось назначить имя делегату события и сделать его доступными извне (public). Для этого представим назначение обработчика события (п.4.)

Это все шаги, которые необходимо сделать для добавления событий.

Следующий пример показывает как, меняя лист в книге Excel или вводя информацию в ячейку (не важно, программно или вручную), мы выводим информацию об этом в приложение, а закрывая книгу — уничтожаем объект Excel.Application, что позволяет избежать зависших процессов Excel в Windows (по крайней мере после закрытия приложения все процессы уничтожаются):

Отметим, что в функции обработчиков событий Excel передаются не ссылки на конкретный объект типа Workbook, Worksheet, Chart, а переменная типа Object, которую перед использованием необходимо явно привести к требуемому типу.

Все события, в имени которых есть слово «Before», позволяют отменить обработку события по умолчанию. Параметр, передаваемый обработчику события, обычно именуется Cancel, а его значение по умолчанию — false. Если присвоить этому параметру True, Excel не выполняет обработку события по умолчанию.

Взаимодействие с серверами автоматизации выполняется аналогично выполнению фонового процесса и, поэтому, доступа к элементам, тем, которые представлены контролами или являются свойствами WindowsForm), из функций делегатов нет (хотя при выполнении, например textBox1.Text=»Перешли на лист = » + ((Excel.Worksheet)Sh).Name); прерывания не будет, но и отображения информации также не будет).

Параграф 11. Об особенности использования метода Activate в VS 2005/2008

Кто добросовестно повторял приведенные выше примеры, тот должен был заметить, что при компиляции приложения на строке

Эта двусмысленность в использовании одноименных свойства и метода объявленных в интерфейсе _Worksheet и интерфейсе DocEvents. Оба эти интерфейса наследует класс Worksheet. И, хотя использование метода Activate не приводит к двусмысленности в выполнении кода, для тех, кто привык писать «чистый код» этот «глюк» лучше устранить. Устранение можно выполнить через события Excel (см. предыдущий параграф).

Уберем из предыдущего кода в case 1: две строчки:

Вместо убранных строчек напишем вызов:

Функцию iMySheetActivate запишем следующим образом (как писать код для работы с событиями описано выше):

Делегат может быть и пустым:

Предупреждений компиляции не будет в коде предыдущего параграфа если мы изменим и обработчик нажатия кнопки 4:

Параграф 12. Автозаполнение или работа с диапазонами

Создадим файл 1.xls, в который предварительно запишем информацию, показанную на Рис.13.

Рис 13 Файл xls для автозаполнения

Выполним следующий код:

Результат выполнения кода показан на Рис.14.

Рис 14. Файл xls после автозаполнения

Параграф 13. Некоторые возможности по управлению параметрами Excel

Приведенный ниже код демонстрирует богатство возможностей по управлению параметрами Excel из приложения на C#. Приведенные примеры целесообразно испытывать раздельно (по возможностям) — каждая новая из нескольких приведенных здесь возможностей (их, реально, во много раз больше), начинаются в коде примера фразой «Можно . «.

Заключение. О богатстве возможностей

Богатства возможностей по управлению запущенным приложением потрясающе. Практически, все, что можно сделать в автономно запущенном приложении доступно и из приложения на C#. Каждый может достаточно легко выполнить то или иное действия из приложения, если создаст макрос для этого действия, а, затем, «переведет» код VBA в коды C#.

И, в тоже время, по мнению автора, для начального этапа практической работы по формированию документов из приложения, изложенного материала вполне достаточно. Но, несмотря на это, раздел будет пополняться по мере возникновения какой либо проблемы в практической работе и ее разрешении. Если у Вас есть интересные находки — присылайте — с указанием авторства они будут включены в данный материал.

Молчанов Владислав 1.11.2004г.

Адаптировано к VS 2005/2008 14.10.2007г.

Перепечатка материала без разрешения автора не допускается.

Источник

Для работы с Excel файлами в системе 1C существуют определенные технологии. Организовать взаимодействие системы 1C с внешней программой MS Excel можно через COM-объект «Excel.Application». Также есть возможность наладить взаимодействие с Excel из 1C используя технологию ADO.

Данный пример демонстрирует работу с использованием «Excel.Application». Для работоспособности данного примера на компьютере обязательно должно быть установлено программное обеспечение MS Excel.

Прочитать из существующего Excel Файла

Процедура ПрочитатьСуществующийExcelФайл(ПутьКФайлу)Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = 0;
Excel.Visible = 0;
Исключение
Сообщить(ОписаниеОшибки() + " Программа Exсel не установлена");
Возврат;
КонецПопытки;

Книга

= Excel.Workbooks.Open(ПутьКФайлу);
КоличествоЛистов = Книга.Sheets.Count;//Перебор листов
Для НомерЛиста = 1 По КоличествоЛистов Цикл

Лист

= Книга.Sheets(НомерЛиста);
КоличествоСтрок = Лист.Cells(1, 1).SpecialCells(11).Row;
КоличествоКолонок = Лист.Cells(1, 1).SpecialCells(11).Column;//Перебор строк
Для НомерСтроки = 1 По КоличествоСтрок Цикл//Перебор колонок
Для НомерКолонки = 1 По КоличествоКолонок Цикл
ЗначениеЯчейки = Лист.Cells(НомерСтроки, НомерКолонки).Value;
//Выполнение действий с полученным значением
//...
//...
КонецЦикла;КонецЦикла;КонецЦикла;

Excel

.Workbooks.Close();
Excel.Application.Quit();КонецПроцедуры

Записать в существующий Excel Файл

Процедура ЗаписатьСуществующийExcellФайл(ПутьКФайлу)Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = 0;
Excel.Visible = 0;
Исключение
Сообщить(ОписаниеОшибки() + " Программа Exсel не установлена");
Возврат;
КонецПопытки;

Книга

= Excel.Workbooks.Open(ПутьКФайлу);

Лист

= Книга.Sheets(1);
//Установить значение в ячейку
Лист.Cells(1, 1).Value = "Тестовое значение";
Книга.Save();

Excel

.Workbooks.Close();
Excel.Application.Quit();КонецПроцедуры

Создать новый Excel Файл

Процедура СоздатьНовыйExcellФайл(ПутьКФайлу)Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = 0;
Excel.Visible = 0;
Исключение
Сообщить(ОписаниеОшибки() + " Программа Exсel не установлена");
Возврат;
КонецПопытки; //Автоматически будут созданы три листа
Книга = Excel.WorkBooks.Add();
//Получить первый лист
Лист = Книга.Sheets(1);
//Установить значение в ячейку
Лист.Cells(1, 1).Value = "Тестовое значение";Попытка
Книга.SaveAs(ПутьКФайлу);
Исключение
Сообщить(ОписаниеОшибки() + " не удалось сохранить файл");
КонецПопытки;

Excel

.Workbooks.Close();
Excel.Application.Quit();КонецПроцедуры

Вообще 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 основные кнопки):

  1. Выгрузка табличной части в подготовленный файл MS Excel
  2. Загрузка табличной части из файла.


Алгоритм выгрузки/загрузки в MS Excel

Алгоритм выгрузки следующий:

  1. Выгружаем табличную часть в таблицу значений
  2. Создаём новый COM-объект Excel.Application
  3. Выбираем файл, открываем файл книги MS Excel
  4. Переходим на заданный лист книги
  5. Выгружаем данные в файл
  6. Закрываем книгу, выходим из COM-объекта.

Алгоритм загрузки следующий:

  1. Создаём новый COM-объект Excel.Application
  2. Выбираем файл, открываем файл книги MS Excel
  3. Переходим на заданный лист книги
  4. Загружаем данные из файла в таблицу значений
  5. Закрываем книгу, выходим из COM-объекта
  6. Таблицу значений выгружаем в табличную часть.

Операция выгрузки и загрузки данных о номенклатуре происходит в заранее подготовленный шаблон 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С, а также шаблон для загрузки/выгрузки можно скачать по ссылке ниже.

Указанные здесь процедуры и функции я постарался сделать универсальными. Они могут быть применены для широкого круга прикладных задач.

Скачать

  • Download source files — 170 Kb
  • Download demo project — 503 Kb

Sample Image - EasyIF_screenshot.jpg

Introduction

This sample add-in demonstrates how the Excel C API can be used to develop add-ins, in conjunction with COM automation. Back in the dark ages (before COM add-ins), programs like Excel and Word exposed a C API that developers could use to develop add-ins for. They even came up with special DLL file name extensions (XLL for Excel and WLL for Word) to denote these as Office add-in modules.

The general overview of how this application is constructed:

  • An Excel C API based DLL module that interfaces with Excel
  • Visual components added to the Excel menu structure using the C API
  • Standard MFC-style coding for the add-in UI, dialogs, etc.
  • COM automation to control certain aspects of Excel that are not exposed via the C API

The basic interface to the Excel C API involves exporting certain named functions that Excel calls automatically (similar to ISAPI). These functions then register the necessary Formulas, Menu items and Toolbars by interacting with Excel via the Excel4 function, passing the names and corresponding function pointers. Data is passed back and forth in this function using an unusual data structure, the XLOPER. This structure predates OLE and is very similar in concept to the VARIANT data type structure. There are some structure members and concepts specific to Excel, however. When the add-in functions are called, care must be taken not to assume that the function is running on any specific thread, since Excel calculation engine may call your function as part of a recalc, or the Excel UI may call the function as part of the formula builder.

Overview Of The Addin’s Functionality

With EasyIf, simple to comprehensive logical functions such as if/then relationships, and lookup and reference functions such as VLOOKUP and HLOOKUP can be combined into one easy worksheet function, replacing complex and at times, limiting standard functions. This Excel add-in product is easy to use and maintain, and delivers powerful logical relationship comparisons, unprecedented lookup capabilities and accurate value selection that were only previously available through custom macro programming. The add-in contains a new comparative analysis function that, depending on the comparison criteria, Excel either does not offer or is so difficult and limiting to use via built-in logical and lookup/reference functions that users shun away from this comparative analysis thereby missing some of the value that Excel can provide. Click here for the official User’s Guide for a more complete description of the functionality.

Secondary Topic Of Interest

The heart of the add-in’s functionality involves a weighted pattern-matching engine. This engine allows for complex, exception based selection and determination. Consider the following example:

The rate for Programming services is $100, except if it is done by a Senior developer then the rate is $120. But, if the work is done by someone from the San Francisco area, the rates are $115 and $135 respectively. These rates apply for all customers, except for GOLD level customers who receive a 10% discount. Oh, by the way, we have also negotiated specific, lower rates for special customers based on contracts.

How would you:

  1. code this so that it is maintainable and
  2. be able to do an Excel spreadsheet on this?

With the Exception-based pattern-matching engine, you could set up a table that contains the following entries, where ‘*’ denotes a wildcard.

Cust Level Customer Location Service WorkerClass Rate
* * * PROG * 100
* * * PROG SENIOR 120
* * SF PROG * 115
* * SF PROG SENIOR 135
GOLD * * PROG * 90
GOLD * * PROG SENIOR 108
GOLD * SF PROG * 103.50
GOLD * SF PROG SENIOR 121.50
* Microsoft * PROG * 76
* Microsoft * PROG SENIOR 87

Using the pattern matching algorithm, this is all that would need to be maintained. The algorithm automatically selects the most fully matched entry, returning the rate in this case. Since it supports different data types for the columns, date-sensitivity could be added without any recoding by simply inserting additional columns. Columns can be configured to use extended comparison operators as well, including <, <=, >, >= and <>. Any number of these tables may be defined, each having a different structure and return type. For more information, consult the demo or Matrix.h and Matrix.cpp.

Important Program Note

The source code provided is for viewing only and will NOT compile, as it uses a third-party commercial library for certain functions. For those of you who have a license for Dundas Ultimate Grid 97 for MFC, you may have a chance of compiling it.

Conclusion

Hopefully, this code will illustrate that the good old fashioned C API can coexist with current COM technology, allowing the developer to use each technology where appropriate. Additionally, it provides a (hopefully) unique concept on how to easily handle complex decision trees and lookups of constantly changing values.

Starting developing in 1980’s using Basic, MSC 5.0, Btrieve and DBFs. Back when men were men and there were no wizards. Since then, I have developed payroll processing system, general ledger packages, billing systems, project accounting systems, order entry, a report writer, email systems, development frameworks, C++ based Web Application Server and others that have long been forgotten.

Professionally, I have been a developer, sr. developer, development lead, architect, chief architect, CTO, director of development, and consultant. I am also in charge of changing the bottled water when empty.

Понравилась статья? Поделить с друзьями:
  • Combine the given attributes with the nouns translate the new word combinations civil main
  • Com to excel программа
  • Com puzzle search word
  • Combine tables in word
  • Com object with excel