Содержание
- 1 Excel VBA Macro script
- 2 Создаем собственную библиотеку Excel макросов — Personal.xlsb
-
- 2.0.1 Чуть-чуть лирики
- 2.0.2 Собственно, код
-
- 3 Что такое VBA
- 4 Объекты, коллекции, свойства и методы
- 5 Как начать
- 6 Макросы в Excel
- 7 Пример 1
- 8 Пример 2
- 9 Пример 3
- 10 Пример 4
-
- 10.0.1 Первый способ. Скрипт «от руки».
- 10.0.2 Второй способ. Скрипт продаж в офисных программах (Excel, Word и тд)
- 10.0.3 Третий способ. Специальные сервисы «Конструкторы скриптов продаж»
- 10.0.4 Полезные ссылки:
-
В процессе работы неоднократно приходиться сталкиваться с табличными процессорами типа Excel. И хотя это не совсем САПР, но информацию в рамках BIM контекста хочешь не хочешь, а приходится обрабатывать, либо с помощью Базы Данных, либо в тех самых экселевских табличках. А лучше и так и эдак.
Естественно, как и во всем, что связанно с компьютером эту деятельность тоже можно изрядно упростить с помощью автоматизации. С появлением таких вещей как Pivot Tables и Power Queries — так и вовсе становится не понятно как работали с информацией до этого. Но тут мы поговорим о старых добрых ламповых макросах на VBA.
Excel VBA Macro script
Макросы в экселе пишут на VBA (Visual Basic Advance) — слегка переработанный под нужды офисного пакета старый добрый Бейсик, со всеми своими достоинствами и недостатоками. Сами программы по умолчанию являются частью эксель файла. И убедится в этом можно с помощью соответствующей консоли (Microsoft Visual Basic for Application)
Добраться до них можно в любое время нажав сочетание клавишь Alt+F11
Но сначала надо включить вкладку Developers в стандартной ленте экселя.
Для этого:
- Ннаводим курсор на ленту и нажимаем Правую Клавишу Мыши (ПКМ)
- В открывшемся списке выбираем — Customize the Ribbon (Настройка Ленты)
- Ищем как показано на скриншоте пункт Developer (Разработка) и нажимаем чтобы появилась галочка
- Ок.
Путем этих не хитрых манипуляций мы получили доступ к панели разработчика в Excel — не будем особо заострять на ней внимание. Нам там понадобится буквально несколько кнопок
— Visual Basic — собственно уже обусжденная выше консоль для работы со скриптами.
— Macos — список доступных макросов для использования.
— Record Macro — эта кнопка позволяет включить запись ваших действий с табличным редактором.
Ну и дальше порядок работы довольно простой — запускаете запись макроса, производите необходимые манипуляции с данными, останавливаете запись (той же кнопкой что и включили), идете в редактор, правите если необходимо. Потом с помощью списка макросов вызываете вновь созданный макрос в любое удобное время.
Однако есть нюанс. Созданный макроскрипт будет по умолчанию доступен только в одном эксель файле. Скопировать его в другой — конечно можно, но довольно заморочно. Есть ли выход из этой ситуации? Конечно!
Создаем собственную библиотеку Excel макросов — Personal.xlsb
Для этого нам нужно создать файл Personal.xlsb. Создается он один раз, и потом автоматически подгружается Экселем, благодаря чему сохраненные в нем Скрипты и функции становятся доступны во всех ваших файлах. Другой плюс — теперь они не сохраняются в самих файлах, и соответственно можно без опаски передавать результаты за пределы компании.
Собственно смотрим на картинку:
1. Необходимо включить макрос на запись.
2. В появившемся окне в выпадающем списке выбрать пункт — Personal Macro Workbook. Если такого файла не существует — он будет создан автоматические (то что нам и нужно)
3. Запускаем скрипт на запись
4. И останавливаем её.
Готово. Теперь у нас есть файл в который наши модули и функции можно закинуть единожды, а доступны они будут сразу во всех эксель файлах. К тому же так они не утекут за пределы компании, вместе с файлами.
Небольшой топик-шпаргалка для быстрого написания скриптов для автоматической обработки документов ms office’а. А так же для помощи в преодолении синдрома чистого листа.
Как правильно заметили в недавнем топике, сама работа скрипта может быть и не быстрой, но чаще важнее сам результат, да и объёмы далеко не всегда такие большие. Зато Automation позволяет написать скрипт практически на любом языке. Здесь я выдам заготовки для JavaScript и IronPython, но, надеюсь, в комментариях найдётся место и для других языков (например, на PowerShell).
Чуть-чуть лирики
Для работы через automation нужен следующий минимум:
- MS Office (если есть документы, то он, видимо, есть/будет установлен)
- Интерпретатор выбранного языка (для JS, VBS и PowerShell этот пункт не актуален)
- Ещё раз MS Office для подглядывание за генерацией кода в VBA (в записываемых макросах)
Ещё раз повторюсь. Цель — быстро написать скрипт без сложных требований (производительность, встраивание, работа без ms office и т.п.).
Собственно, код
Имхо, самый разумный вариант — это JScript или VBScript (точнее Windows script host), т.к. интерпретатор уже идёт с операционной системой, и можно раздавать скрипт друзьям/коллегам, не требуя от них никаких дополнительных действий — перетащил xls(x)-файл на скрипт в explorer’е и работа пошла:
var excel = WScript.CreateObject("Excel.Application"); var fileName = WScript.Arguments.Item(0); try { main(); } catch(e) { // Чтобы процесс не завис в памяти delete excel; throw e; } function main() { //excel.Visible = true; // Иногда хочется поспать перед экраном, где что-то происходит, но так работает дольше //var book = excel.Workbooks.Add(); // Новая книга (создать) var book = excel.Workbooks.Open(fileName); // Старая книга var sheet = book.Worksheets.Item(1); // (в VBA нумерация с единицы) // Что-то делаем for (var i = 1; i Macros -> Record macro..., имя значения не имеет), открываем его код (View -> Macros -> View macros...) и делаем по образу и подобию. Сама запись макроса — просто набор действий, которые хочется автоматизировать. Например, вставить или изменить какое-то значение, поменять цвет/шрифт и т.п. Запись макроса лучше производить в отдельном документе, во избежание. Для лучшей ориентации в мире объектов объектном мире Excel — система классов (тоже самое, но для Office 2010). Небольшой бонус: константы для цветовых индексов. P.S. Где-то у меня был код для работы с Automation из C++, но это уже совсем другая история :)
Немногие знают, что первая версия популярного продукта Microsoft Excel появилась в 1985 году. С тех пор он пережил несколько модификаций и востребован у миллионов пользователей по всему миру. При этом многие работают лишь с малой толикой возможностей этого табличного процессора и даже не догадываются, как им могло бы облегчить жизнь умение программирования в Excel.
Что такое VBA
Программирование в Excel осуществляется посредством языка программирования Visual Basic for Application, который изначально встроен в самый известный табличный процессор от Microsoft.
К его достоинствам специалисты относят сравнительную легкость освоения. Как показывает практика, азами VBA могут овладеть даже пользователи, которые не имеют навыков профессионального программирования. К особенностям VBA относится выполнение скрипта в среде офисных приложений.
Недостатком программы являются проблемы, связанные с совместимостью различных версий. Они обусловлены тем, что код программы VBA обращается к функциональным возможностям, которые присутствуют в новой версии продукта, но отсутствуют в старой. Также к минусам относят и чрезмерно высокую открытость кода для изменения посторонним лицом. Тем не менее Microsoft Office, а также IBM Lotus Symphony позволяют пользователю применять шифрование начального кода и установку пароля для его просмотра.
Объекты, коллекции, свойства и методы
Именно с этими понятиями нужно разобраться тем, кто собирается работать в среде VBA. Прежде всего необходимо понять, что такое объект. В Excel в этом качестве выступают лист, книга, ячейка и диапазон. Данные объекты обладают специальной иерархией, т.е. подчиняются друг другу.
Главным из них является Application, соответствующий самой программе Excel. Затем следуют Workbooks, Worksheets, а также Range. Например, для обращения к ячейке A1 на конкретном листе следует указать путь с учетом иерархии.
Что касается понятия «коллекция», то это группа объектов того же класса, которая в записи имеет вид ChartObjects. Ее отдельные элементы также являются объектами.
Следующее понятие — свойства. Они являются необходимой характеристикой любого объекта. Например, для Range — это Value или Formula.
Методы — это команды, показывающие, что требуется сделать. При написании кода в VBA их необходимо отделять от объекта точкой. Например, как будет показано в дальнейшем, очень часто при программировании в «Эксель» используют команду Cells(1,1).Select. Она означает, что необходимо выбрать ячейку с координатами (1,1) т.е. A1.
Вместе с ней нередко используется Selection.ClearContents. Ее выполнение означает очистку содержимого выбранной ячейки.
Как начать
Прежде всего требуется создать файл и сохранить его, присвоив имя и выбрав тип «Книга Excel с поддержкой макросов».
Затем необходимо перейти в приложение VB, для чего достаточно воспользоваться комбинацией клавиш «Alt» и «F11». Далее:
- в строке меню, расположенном в верхней части окна, нажимают на иконку рядом с иконкой Excel;
- выбирают команду Mudule;
- сохраняют, нажав на иконку с изображением floppy disk;
- пишут, скажем так, набросок кода.
Он выглядит следующим образом:
Sub program ()
‘Наш код
End Sub
Обратите внимание, что строка «’Наш код» будет выделена другим цветом (зеленым). Причина в апострофе, поставленном в начале строки, который обозначает, что далее следует комментарий.
Теперь вы можете написать любой код и создать для себя новый инструмент в VBA Excel (примеры программ см. далее). Конечно, тем, кто знаком с азами Visual Basic, будет намного проще. Однако даже те, кто их не имеет, при желании смогут освоиться достаточно быстро.
За таким названием скрываются программы, написанные на языке Visual Basic for Application. Таким образом, программирование в Excel — это создание макросов с нужным кодом. Благодаря этой возможности табличный процессор Microsoft саморазвивается, подстраиваясь под требования конкретного пользователя. Разобравшись с тем, как создавать модули для написания макросов, можно приступать к рассмотрению конкретных примеров программ VBA Excel. Лучше всего начать с самых элементарных кодов.
Пример 1
Задача: написать программу, которая будет копировать значение содержимое одной ячейки и затем записывать в другую.
Для этого:
- открывают вкладку «Вид»;
- переходят на пиктограмму «Макросы»;
- жмут на «Запись макроса»;
- заполняют открывшуюся форму.
Для простоты в поле «Имя макроса» оставляют «Макрос1», а в поле «Сочетание клавиш» вставляют, например, hh (это значит, что запустить программку можно будет блиц-командой «Ctrl+h»). Нажимают Enter.
Теперь, когда уже запущена запись макроса, производят копирование содержимого какой-либо ячейки в другую. Возвращаются на исходную пиктограмму. Нажимают на «Запись макроса». Это действие означает завершение программки.
Далее:
- вновь переходят на строку «Макросы»;
- в списке выбирают «Макрос 1»;
- нажимают «Выполнить» (то же действие запускается начатием сочетания клавиш «Ctrl+hh»).
В результате происходит действие, которое было осуществлено в процессе записи макроса.
Имеет смысл увидеть, как выглядит код. Для этого вновь переходят на строку «Макросы» и нажимают «Изменить» или «Войти». В результате оказываются в среде VBA. Собственно, сам код макроса находится между строками Sub Макрос1() и End Sub.
Если копирование было выполнено, например, из ячейки А1 в ячейку C1, то одна из строк кода будет выглядеть, как Range(“C1”).Select. В переводе это выглядит, как «Диапазон(“C1”).Выделить», иными словами осуществляет переход в VBA Excel, в ячейку С1.
Активную часть кода завершает команда ActiveSheet.Paste. Она означает запись содержания выделенной ячейки (в данном случае А1) в выделенную ячейку С1.
Пример 2
Циклы VBA помогают создавать различные макросы в Excel.
Циклы VBA помогают создавать различные макросы. Предположим, что имеется функция y=x + x2 + 3×3 – cos(x). Требуется создать макрос для получения ее графика. Сделать это можно только, используя циклы VBA.
За начальное и конечное значение аргумента функции берут x1=0 и x2=10. Кроме того, необходимо ввести константу — значение для шага изменения аргумента и начальное значение для счетчика.
Все примеры макросов VBA Excel создаются по той же процедуре, которая представлена выше. В данном конкретном случае код выглядит, как:
Sub programm()
x1 = 1
x2 = 10
shag = 0.1
i = 1
Do While x1 < x2 (цикл будет выполняться пока верно выражение x1 < x2)
y=x1 + x1^2 + 3*x1^3 – Cos(x1)
Cells(i, 1).Value = x1 (значение x1 записывается в ячейку с координатами (i,1))
Cells(i, 2).Value = y (значение y записывается в ячейку с координатами (i,2))
i = i + 1 (действует счетчик);
x1 = x1 + shag (аргумент изменяется на величину шага);
Loop
End Sub.
В результате запуска данного макроса в «Эксель» получаем два столбца, в первом из которых записаны значения для x, а во втором — для y.
Затем по ним строится график способом, стандартным для «Эксель».
Пример 3
Для реализации циклов в VBA Excel 2010, как и в других версиях, наряду с уже приведенной конструкцией Do While используется For.
Рассмотрим программу, которая создаст столбец. В каждой его ячейке будут записаны квадраты номера соответствующей строки. Использование конструкции For позволит записать ее очень коротко, без использования счетчика.
Сначала нужно создать макрос, как описано выше. Далее записываем сам код. Считаем, что нас интересуют значения для 10 ячеек. Код выглядит следующим образом.
For i = 1 to 10 Next
Команда переводится на «человеческий» язык, как «Повторять от 1 до 10 с шагом один».
Если ставится задача получить столбец с квадратами, например, всех нечетных чисел из диапазона от 1 до 11, то пишем:
For i = 1 to 10 step 1 Next.
Здесь step — шаг. В данном случае он равен двум. По умолчанию отсутствие этого слова в цикле означает, что шаг единичный.
Полученные результаты нужно сохранять в ячейки с номером (i,1). Тогда при каждом запуске цикла с увеличением i на величину шага автоматически будет расти и номер у строки. Таким образом, произойдет оптимизация кода.
В целом код будет выглядеть, как:
Sub program()
For i = 1 To 10 Step 1 (можно записать просто For i = 1 To 10)
Cells(i, 1).Value = i ^ 2 (т.е. в ячейку (i,1) записывается значение квадрата i)
Next (в некотором смысле играет роль счетчика и означает еще один запуск цикла)
End Sub.
Если все сделано правильно, в том числе запись и запуск макроса (см. инструкцию выше), то при его вызове каждый раз будет получаться столбец заданного размера (в данном случае состоящий из 10 ячеек).
Пример 4
В повседневной жизни сплошь и рядом возникает необходимость принять то или иное решение в зависимости от какого-то условия. Не обойтись без них и в VBA Excel. Примеры программ, где дальнейший ход выполнения алгоритма выбирается, а не предопределен изначально, чаще всего используют конструкцию If …Then (для сложных случаев) If …Then …END If.
Рассмотрим конкретный случай. Предположим, необходимо создать макрос для «Эксель», чтобы в ячейку с координатами (1,1) было записано:
1, если аргумент положительный;
0, если аргумент нулевой;
-1, если аргумент отрицательный.
Создание такого макроса для «Эксель» начинается стандартным способом, через использование «горячих» клавиш Alt и F11. Далее записывается следующий код:
Sub program()
x= Cells(1, 1).Value (эта команда присваивает x значение содержимого ячейки с координатами (1, 1))
If x>0 Then Cells(1, 1).Value = 1
If x=0 Then Cells(1, 1).Value = 0
If x
09 Мар 3 способа написать и оформить скрипт продаж
Давайте разберемся, как обычно создаются скрипты продаж?
В своей практике я обычно сталкиваюсь с 3 способами написания и оформления скриптов продаж. Давайте по порядку рассмотрим эти способы. Напишите в комментариях, используете ли Вы скрипты продаж и, если ДА, то каким именно способом Вы это делаете.
Первый способ. Скрипт «от руки».
Вы можете написать скрипт продаж (или хотя бы примерный сценарий общения с клиентом) на листочке, положить перед собой и использовать его как шпаргалку во время разговора с клиентом.
Это может выглядеть так:
Никаких затрат с Вашей стороны.
Но и эффективность таких скриптов оставляет желать лучшего:
- здесь не предусмотрены различные сценарии разговора и не прописана отработка возражений (а если прописать, это займет много места и затруднит использование скрипта);
- пользоваться таким скриптом может, пожалуй, только тот, кто его написал. Его сложно тиражировать на новых сотрудников;
- нет системного подхода к телефонным продажам, о котором я рассказываю на онлайн-тренинге 10 звонков — 10 продаж.
Этот способ может быть уместен, когда Вы делаете разовые звонки каким-то клиентам и, чтобы ничего не упустить, тезисно выписываете содержание разговора.
К сожалению, такой способ часто используется во многих компаниях малого и среднего бизнеса. Обычно это бывает, когда система телефонных продаж не настроена и менеджеры делают звонки как умеют и используют те инструменты, которые знают :-).
Второй способ. Скрипт продаж в офисных программах (Excel, Word и тд)
Более продвинутый и системный подход к внедрению скриптов продаж — это составление и использование скриптов в офисных программах, таких как Excel или Word (или аналогичных).
Вы можете прописать все возможные варианты возражений и отговорок клиентов, свою аргументацию и способы мотивации клиента принимать решение «здесь и сейчас» в одном файле, а потом с помощью создания гиперссылок автоматизировать скрипт.
В этом случае менеджеру будет удобно им пользоваться: услышал возражение — нажал на ссылку в скрипте — на экране появился ответ на это возражение.
Именно такой принцип создания скриптов я использовал в курсе Конструктор скриптов продаж. Я разобрал не только фразы и речевые обороты, которые повышают конверсию звонков, но и показал, как автоматизировать скрипт в обычном экселе.
Плюсы этого подхода в том, что Вам не нужно платить ежемесячную абонентскую плату за пользование сервисами. Скорее всего, у Вас и так есть Excel или Word — а это значит, что Вы можете один раз составить скрипт и начать использовать его всем отделом продаж.
Минусы — нет интеграции с CRM системами и телефонией.
Третий способ. Специальные сервисы «Конструкторы скриптов продаж»
В последнее время популярность набирают специальные сервисы, которые позволяют конструировать скрипты продаж. Обычно это происходит через веб-интерфейс.
Вы заходите на сайт сервиса — регистрируетесь — начинаете рисовать свой скрипт продаж.
Это может выглядеть вот так:
Возможно, картинка выглядит сложно, но на самом деле процесс создания скриптов продаж достаточно комфортен и позволяет даже новичку легко сориентироваться.
При использовании скрипта экран выглядит гораздо проще: есть фраза менеджера, есть варианты ответов клиентов. Менеджер слушает и нажимает на нужную кнопку.
Я протестировал некоторые сервисы конструкторы скриптов продаж и сделал для себя определенные выводы. В следующей статье я поделюсь с Вами и сделаю обзор некоторых сервисов по созданию скриптов, которые мне больше понравились.
Преимуществами таких сервисов, на мой взгляд, являются
- удобство создания скриптов (все наглядно, скрипт в буквальном смысле можно рисовать);
- удобство использования скриптов сотрудниками (даже новичок может легко сориентироваться);
- продвинутая аналитика работы со скриптом (Вы сможете отслеживать, на каком этапе чаще всего заканчивается разговор с клиентом, какие возражения вызывают затруднения, какая конверсия звонков у каждого сотрудника);
- интеграция с CRM системами и телефонией (многие конструкторы скриптов это поддерживают).
Как Вы понимаете, за такие удобства нужно платить. Обычно взимается ежемесячная абонентская плата за каждого менеджера, который пользуется системой.
В следующих статьях поподробнее расскажу о конструкторах скриптов продаж.
Напишите в комментариях, какими способами пользуетесь Вы в своей работе.
С уважением, Олег (дружить в ВК, инстаграм)
Полезные ссылки:
- 5 способов больше продавать по телефону — полезная статья с конкретными рекомендациями
- Видеокурс «Конструктор скриптов телефонных продаж» — это целый комплект материалов, подготовленный с одной целью — чтобы Вы могли за несколько часов создать полноценный скрипт продаж с учетом особенностей Вашего бизнеса.
- Видеокурс «Клоузер: всегда закрывай сделку» — система закрытия сделок и более 40 мощных техник помогут Вам закрывать больше сделок в любом бизнесе — от мелкой розницы до крупных корпоративных продаж.
- Бесплатный курс «Быстрый старт в продажах» — даже если Вы новичок в продажах, курс поможет Вам привлечь новых клиентов уже в течение 1 недели, построить системную работу и повысить профессионализм в области продаж.
- Бесплатный аудит Ваших продаж! Начните с аудита Ваших продаж! Это бесплатно и полезно. Я проверю более 50 точек роста Ваших продаж и вышлю Вам PDF отчет по результатам аудита в течение 5 дней.
- Youtube канал «ПораРасти» – подписывайтесь сейчас, чтобы получать доступ к новым материалам первыми;
- Группа в ВК «ПораРасти» – сообщество для тех, кто хочет продавать красиво и легко, развивать собственный бизнес, приносить людям реальную пользу, а не заниматься впариванием. Присоединяйтесь сейчас! Здесь много бесплатных материалов, PDF и т.д.
js-xlsx введение
кSheetJSПроизведеноjs-xlsx
Это очень удобная библиотека инструментов, которой для чтения и экспорта в Excel нужен только чистый JS. Она имеет мощные функции, поддерживает множество форматов и поддерживаетxls
、xlsx
、ods
(Собственный формат файлов таблицы OpenOffice) и более десятка форматов. Вся эта статья основана наxlsx
Возьмем, к примеру, формат.
- Официальный гитхаб:https://github.com/SheetJS/js-xlsx
- Онлайн-демонстрационный адрес поддерживающей демонстрации для этой статьи:http://demo.haoji.me/2017/02/08-js-xlsx/
- Эта статья впервые была опубликована у меня синхронноличный блогсБлог сад。
1.1. Совместимость
Совместимость следующая:
1.2. Как пользоваться
dist
В каталоге много JS-файлов, обычно используйтеxlsx.core.min.js
довольно,xlsx.full.min.js
Он содержит все функциональные модули.
непосредственныйscript
Этикетка может быть введена:
<script type="text/javascript" src="./js/xlsx.core.min.js"></script>
Читать в Excel
Чтение в Excel происходит в основном черезXLSX.read(data, {type: type});
Способ достижения, ответьте на звонокWorkBook
Основные значения типа следующие:
base64
: Читать в режиме base64;binary
: Формат BinaryString (n-й байт — это data.charCodeAt (n))string
: Строка в кодировке UTF8;buffer
: nodejs Buffer;array
: Uint8Array, 8-битный беззнаковый массив;file
: Путь к файлу (поддерживается только в nodejs);
2.1. Получить объект книги
2.1.1. Чтение локальных файлов
Непосредственно по коду:
// читаем локальный файл Excel
function readWorkbookFromLocalFile(file, callback) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
if(callback) callback(workbook);
};
reader.readAsBinaryString(file);
}
2.1.2. Чтение сетевых файлов
// Чтобы прочитать файл Excel из Интернета, URL-адрес должен находиться в том же домене, иначе будет сообщено об ошибке
function readWorkbookFromRemoteFile(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if(xhr.status == 200) {
var data = new Uint8Array(xhr.response)
var workbook = XLSX.read(data, {type: 'array'});
if(callback) callback(workbook);
}
};
xhr.send();
}
2.2. Подробная рабочая тетрадь
2.2.1. Workbook Object
workbook
Что в нем, распечатаем и посмотрим:
можно увидеть,SheetNames
В нем сохраняются все названия листов, а затемSheets
Конкретное содержимое каждого листа сохраняется (мы называем этоSheet Object
). Каждыйsheet
Через что-то вродеA1
Такое значение ключа сохраняет содержимое каждой ячейки, и мы называем его объектом ячейки (Cell Object
):
2.2.2. Sheet Object
КаждыйSheet Object
Представляет форму, если она не!
Те, что в начале, указывают на обычныеcell
, В противном случае это означает какое-то особое значение, а именно:
sheet['!ref']
: Указывает диапазон всех ячеек, например, от A1 до F8, он записывается какA1:F8
;sheet[!merges]
: Хранить некоторую информацию о слиянии ячеек, это массив, каждый массив состоит изs
сe
Составьте композицию объекта,s
Значит старт,e
Означает конец,r
Представляет строку,c
Представляет столбец;- и многое другое;
Что касается слияния ячеек, в принципе не проблема понять следующую картину:
Результаты приведены ниже:
2.2.3. Объект Cell
Каждая ячейка — это объект (Cell Object
),Естьt
、v
、r
、h
、w
И другие поля (см.Здесь):
- t: указывает тип содержимого,
s
Представляет тип строки,n
Представляет числовой тип,b
Представляет логический тип,d
Представляет тип даты и т. Д. - v: представляет исходное значение;
- f: представляет формулу, например
B2+B3
; - h: HTML-контент
- w: форматированный контент
- r: богатый текстовый контент
rich text
- и многое другое
2.2.4. Читать книгу
Обычный метод:
// читаем файл Excel
function outputWorkbook(workbook) {
var sheetNames = workbook.SheetNames; // набор имен рабочих листов
sheetNames.forEach(name => {
var worksheet = workbook.Sheets [name]; // Указанный рабочий лист можно получить только по имени рабочего листа
for(var key in worksheet) {
// v - исходное значение прочитанной ячейки
console.log(key, key[0] === '!' ? worksheet[key] : worksheet[key].v);
}
});
}
в соответствии с!ref
Определите сферу применения Excel, а затем в соответствии с!merges
Убедитесь, что ячейки объединены (если есть), и, наконец, выведите всю таблицу, что вызывает затруднения. К счастью, сам плагин уже написал инструментXLSX.utils
Для непосредственного использования, без нашего собственного обхода, выходные данные инструмента в основном включают следующее:
Некоторые из них обычно не используются, наиболее часто используются:
XLSX.utils.sheet_to_csv
: Создать формат CSVXLSX.utils.sheet_to_txt
: Создать текстовый форматXLSX.utils.sheet_to_html
: Создать формат HTMLXLSX.utils.sheet_to_json
: Выходной формат JSON
Чаще всего используютсяsheet_to_csv
или жеsheet_to_html
, Формат, объединение ячеек и другая информация будут игнорироваться при преобразовании в CSV, поэтому сложные таблицы могут быть неприменимы. Если вы конвертируете в html, ячейки будут объединены, но результат будет<html></html>
Код вместо<table></table>
, Это неудобно, когда вам нужно внести некоторые изменения в форму, поэтому вам все равно придется использовать соответствующие инструменты в зависимости от ситуации.
Вот простой пример вывода результатов путем преобразования в CSV, вы можете щелкнуть здесь, чтобы просмотретьДЕМО онлайн:
function readWorkbook(workbook)
{
var sheetNames = workbook.SheetNames; // набор имен рабочих листов
var worksheet = workbook.Sheets [sheetNames [0]]; // здесь мы читаем только первый лист
var csv = XLSX.utils.sheet_to_csv(worksheet);
document.getElementById('result').innerHTML = csv2table(csv);
}
// Преобразование csv в простую таблицу, игнорирование слияния ячеек, добавление индекса, аналогичного excel, в первой строке и первом столбце
function csv2table(csv)
{
var html = '<table>';
var rows = csv.split('n');
rows.pop (); // последняя строка бесполезна
rows.forEach(function(row, idx) {
var columns = row.split(',');
columns.unshift (idx + 1); // добавляем индекс строки
if (idx == 0) {// добавляем индекс столбца
html += '<tr>';
for(var i=0; i<columns.length; i++) {
html += '<th>' + (i==0?'':String.fromCharCode(65+i-1)) + '</th>';
}
html += '</tr>';
}
html += '<tr>';
columns.forEach(function(column) {
html += '<td>'+column+'</td>';
});
html += '</tr>';
});
html += '</table>';
return html;
}
Экспорт в Excel
Существует два типа экспорта: один основан на существующей модификации Excel, другой — нового поколения, первый относительно прост, здесь мы сосредоточимся на втором.
3.1. Создайте собственный рукописный код
Экспорт файла Excel, в основном, как его создатьsheet
, Здесь мы пишем простой пример csv для Excel:
// csv в объект листа
function csv2sheet(csv) {
var sheet = {}; // лист, который будет сгенерирован
csv = csv.split('n');
csv.forEach(function(row, i) {
row = row.split(',');
if(i == 0) sheet['!ref'] = 'A1:'+String.fromCharCode(65+row.length-1)+(csv.length-1);
row.forEach(function(col, j) {
sheet[String.fromCharCode(65+j)+(i+1)] = {v: col};
});
});
return sheet;
}
// Преобразование листа в объект blob окончательного файла Excel, а затем использование URL.createObjectURL для загрузки
function sheet2blob(sheet, sheetName) {
sheetName = sheetName || 'sheet1';
var workbook = {
SheetNames: [sheetName],
Sheets: {}
};
workbook.Sheets[sheetName] = sheet;
// Создание элементов конфигурации для Excel
var wopts = {
bookType: 'xlsx', // тип создаваемого файла
bookSST: false, // Следует ли генерировать общую таблицу строк, официальное объяснение состоит в том, что если она включена, скорость генерации уменьшится, но есть лучшая совместимость с устройствами IOS более низкой версии
type: 'binary'
};
var wbout = XLSX.write(workbook, wopts);
var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});
// Строка в ArrayBuffer
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return blob;
}
Получите объект blob выше, и вы можете загрузить его напрямую, см. Мой предыдущийJS всплывает диалоговое окно загрузкиИнкапсулирован внутриopenDownloadDialog
метод:
/**
* Общий метод открытия диалогового окна загрузки не тестировался на совместимость
* @param url-адрес загрузки, это также может быть объект blob, обязательно
* @param saveName имя файла сохранения, необязательно
*/
function openDownloadDialog(url, saveName)
{
if(typeof url == 'object' && url instanceof Blob)
{
url = URL.createObjectURL (url); // Создание адреса большого двоичного объекта
}
var aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName || ''; // новый атрибут HTML5, укажите имя файла сохранения, суффикс не требуется, обратите внимание, что он не вступит в силу в режиме file: ///
var event;
if(window.MouseEvent) event = new MouseEvent('click');
else
{
event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
aLink.dispatchEvent(event);
}
Таким образом, окончательная загрузка выглядит следующим образом:
// Передаем csv, и после выполнения появится окно загрузки
function exportExcel(csv) {
var sheet = csv2sheet(csv);
var blob = sheet2blob(sheet);
openDownloadDialog (blob, 'Export.xlsx');
}
3.2. Используйте официальные инструменты для создания
На самом деле, нам не нужно писать ни один из вышеперечисленных кодов. Чиновник предоставил нам готовые инструменты, в основном в том числе:
aoa_to_sheet
: Этот класс инструментов является наиболее мощным и практичным.Преобразование двумерного массива в лист автоматически обработает числовые, строковые, логические, даты и другие типы данных;table_to_sheet
: Поставить одинtable dom
Непосредственно преобразованный в лист, он будет автоматически распознанcolspan
сrowspan
И преобразовать его в соответствующую ячейку и объединить;json_to_sheet
: Преобразовать массив объектов в лист;
aoa_to_sheet
Пример:
var aoa = [
["Имя", "Пол", "Возраст", "Время регистрации"],
['Zhang San', 'Male', 18 лет, новое свидание ()],
[' ', ' ', 22, новая дата ()]
];
var sheet = XLSX.utils.aoa_to_sheet(aoa);
openDownloadDialog (sheet2blob (лист), 'Export.xlsx');
table_to_sheet
Еще проще, прямоXLSX.utils.table_to_sheet($('table')[0])
Может
3.3. Решение проблемы слияния ячеек
Вообще говоря, интерфейсное поколениеexcel
Вместоcsv
Основная цель — решить проблему, заключающуюся в том, что csv не может выполнить слияние ячеек. В противном случае было бы неплохо напрямую экспортировать файл csv. Зачем вводить несколько сотен килобайт плагинов.
Предположим, мы хотим сгенерировать файл Excel в следующем формате, гдеA1-C1
Чтобы объединить ячейки:
код показан ниже:
var aoa = [
['Основная информация', null, null, 'Другая информация'], // Особое внимание следует уделить резервированию 2 нулевых значений за объединенным местом
["Имя", "Пол", "Возраст", "Время регистрации"],
['Zhang San', 'Male', 18 лет, новое свидание ()],
[' ', ' ', 22, новая дата ()]
];
var sheet = XLSX.utils.aoa_to_sheet(aoa);
sheet['!merges'] = [
// Устанавливаем слияние ячеек A1-C1
{s: {r: 0, c: 0}, e: {r: 0, c: 2}}
];
openDownloadDialog (sheet2blob (sheet), 'Слияние ячеек example.xlsx');
Стоит обратить внимание на использование объединенных ячеек.null
Зарезервируйте место, иначе следующий контент (в этом примере четвертый столбецДополнительная информация
) Будет перезаписан.
3.4. Пользовательский стиль
Обычная версия не поддерживает определение шрифтов, цветов, цветов фона и т. Д., Вы можете использовать ее, если вам нужна эта функция.профессиональная версия, Вроде заряжено, потому что официальный сайт не видел адреса загрузки.
Персональный сайт:https://haoji.me
github:https://github.com/sxei
Сад блогов:http://www.cnblogs.com/liuxianan
авторское право © 2012-2018 одноклассник Xiaominggrapecity.com.cn/spreadjs/excel-online/content/index.html
__Diego__ 0 / 0 / 0 Регистрация: 05.08.2013 Сообщений: 37 |
||||
1 |
||||
28.04.2014, 10:59. Показов 14815. Ответов 6 Метки нет (Все метки)
Доброго времени суток!
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
28.04.2014, 10:59 |
Ответы с готовыми решениями: HTML import COM, Excel, #import в VC++ MySQL import Excel в базу,таблицу… Import From Excel To Lotus 6 |
Roman_rc 26 / 26 / 12 Регистрация: 04.02.2013 Сообщений: 250 |
||||||||
28.04.2014, 11:58 |
2 |
|||||||
добрый день
И еще обязательно используйте EI только у него ActiveXObject есть
1 |
0 / 0 / 0 Регистрация: 05.08.2013 Сообщений: 37 |
|
28.04.2014, 13:12 [ТС] |
3 |
Благодарю, но хотелось и с другими браузерами так же баловаться…
0 |
26 / 26 / 12 Регистрация: 04.02.2013 Сообщений: 250 |
|
28.04.2014, 14:11 |
4 |
Дело в том что в Excel есть своя встроенная среда VBA она работает со всеми объектами штатно. В IE есть такой штатный объект, но вот к сожалению в других браузерах такого объекта нет. Для того чтобы работать с Excel файлами нужен фрэймворк, который будет работать с файлом. Более того такая возможно появилась только с html 5 (объект FileReader). Добавлено через 18 минут
0 |
0 / 0 / 0 Регистрация: 05.08.2013 Сообщений: 37 |
|
28.04.2014, 14:38 [ТС] |
5 |
тогда получается лучше решить эту задачу средствами html 5 ?
0 |
26 / 26 / 12 Регистрация: 04.02.2013 Сообщений: 250 |
|
28.04.2014, 16:11 |
6 |
Теоретически такой фрэймворк создать можно. FileReader объект может читать файлы, изменять их. В Excel 2007 файлы формата .xlsx это просто заZIPованый xml. Соответственно его можно разархивировать, потом пробежаться по нужным элемента, заменить их и т.п. Но не уверен есть уже такой фрэймворк для js. Может на Query есть.
1 |
0 / 0 / 0 Регистрация: 05.08.2013 Сообщений: 37 |
|
28.04.2014, 19:19 [ТС] |
7 |
Спасибо за помощь, буду искать, учить))
0 |
- Download source — 100.2 KB
Introduction
Many times, we have the need to export from a web application data into Excel format. Usually, we have this data already in the browser: as part of a table content, as an instantiation of a model …. The user has reviewed it, s/he is happy with it, and wants to open it in Excel. In this situation, the developer has different options:
- DO NOTHING, do not even offer the option. In this case, the user is forced to select the data directly from the browser, and then copy & paste it into Excel.
- BACK-END, generates the Excel file on the server. I am pretty sure that for whatever back-end you are using (.NET, Java, Node.js, PHP, …) there are many libraries that allow to generate nice Excel files.
- FRONT-END, generate the Excel directly on the browser.
The DO NOTHING approach works most of the time, but usually the results are awful. All cell formatting is lost in the process, multiple cells in the same row get merged,…
The BACK-END approach is the most popular. The available libraries makes implementing this functionality fast and cheap. However, there some drawbacks, which might or might not affect you:
- It uses server resources, this can be a problem in highly loaded systems.
- There is a «latency», the browser has to send the «generate my Excel» request to the server, the server has to generate it and then send back to the browser for download. This translates in a perceptible «delay» between the user pressing the «Export As Excel» button, and the actual file being downloaded
- Usually, the back-end needs to access the same data that is already present in the front-end. For persistent data then, we need a database query, some data cache implemented on the server,… or just the browser sends along with the «generate Excel request» the data to be included. All of them increase back-end workload, network traffic and the aforementioned latency.
Using the FRONT-END approach, all the previous issues just vanish. Usually this is pretty fast, as there is no network involved at all. However, the number of libraries available is quite short, and usually there is some kind of trade-off.
On the one hand, we have libraries that do not generate a true Excel, but another format (XML, CSV,…) that Excel is able to open. They are fine if you just require plain data export, without any of the Excel specifics (more than a Sheet, cell formatting, …)
About the libraries that generate true Excel, either they are small libraries with limited options (i.e.,: no cell formatting at all) or they are big libraries (>1MB) offering the full range of Excel options (js-xlsx
, exceljs
, openxmlsdkjs
,… ) and with, usually a huge documentation.
In this article, I present a small library that presents the most basic functionality in a clean and concise way. Nevertheless, it is the functionality that I have needed for 90% of my Excel generation needs.
Using the Code
The library is intended to be used on the browser, so it is a JavaScript library, with two dependencies:
- JSZip v3.1.3 by Stuart Knightley, http://stuartk.com/jszip
- FileSaver.js by Eli Grey, http://eligrey.com
To use it, we just include them in our <HEAD>
tag:
<script type="text/javascript" src="jszip.js"></script> <script type="text/javascript" src="FileSaver.js"></script> <script type="text/javascript" src="myexcel.js"></script>
The library defines a single global object $JExcel
. This object includes some generic conversions and a generator for Excel objects.
var excel = $JExcel.new(); var excel = $JExcel.new("Arial 10 #333333");
And Excel object defines four methods:
addSheet
addStyle
set
generate
addSheet
is used to add additional sheets to the Excel object. It requires a name. An Excel object always has a default sheet (index 0). Sheets are referenced by their index of creation.
addStyle
is used to register styles in the Excel document. It requires a style definition object which is made of up to 5 properties:
{ fill: "#ECECEC" , border: "none,none,none,thin #333333" font: "Calibri 12 #0000AA B"}); format: "yyyy.mm.dd hh:mm:ss", align: "R T", }
A border definition is made up of a «border style» and «border color in RGB». Allowed border styles are available in the $JExcel.borderStyles
array.
If font-style includes the B character, then the font is bold, U if underlined and I if italic.
There are a number of predefined display formats in the $JExcel.formats
array. It is also possible to personalize them.
For horizontal-align and vertical-align, the following conventions apply: C: center L: left R: right T: top B: bottom -: none.
set
is used to set values or styles on cells/rows/columns/sheets. What is set is decided by the non-undefined parameters. The following rules apply:
- If only a sheet index is defined, the sheet name is set
- If only a sheet index and a row number are defined, a style can be set for the row in the sheet, and a value for the row height
- If only a sheet index and a column number are defined, a style can be set for the column in the sheet and a value for the column width
- If a sheet index, a column and a row number are defined, then a style can be set for the defined cell and a value for its content
The set
method allows a canonical list of parameters, or a single object parameter. In the canonical form, use undefined
as the not-apply value, in the object parameter, just do not include the property.
set(0,undefined,undefined,"Summary"); var fillEC=excel.addStyle ( {fill: "#ECECEC"}); set(2,undefined,1,undefined,fillEC); set( {sheet:2,row:1,style:fillEC}); var Arial10B=excel.addStyle ({font: "Arial 10 B"}); set( {sheet:0,col:5,row:3,value: "HELLO",style:Arial10B}); set(0,5,3,"HELLO",Arial10B);
The generate
method generates an Excel WorkBook and makes it available for downloading.
Points of Interest
The XLSX format is just a bunch of XML files that are zipped together. This XML files follow the OpenXML convention. The library works by defining a model of Excel objects (sheets, rows, cells, styles,…) that are SET in memory, when the generate
method is called, the necessary XML nodes for the Excel obejcts are created.
These XML nodes are then «printed» and merged with the OpenXML templates, then everything is zipped and the resulting stream is ready for download.
EXCEL does not handle date times as JavaScript, They use different EPOCH moments. The library defines the following conversion functions $JExcel.toExcelLocalTime(jsDate)
, $JExcel.toExcelUTCTime(jsDate)
For handling RGB values, the following function is also provided $JExcel.rgbToHex(red,green,blue)
.
Sample
The following sample…
function randomDate(start, end) { var d= new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); return d; } var excel = $JExcel.new("Calibri light 10 #333333"); excel.set( {sheet:0,value:"This is Sheet 0" } ); var evenRow=excel.addStyle( { border: "none,none,none,thin #333333"}); var oddRow=excel.addStyle ( { fill: "#ECECEC" ,border: "none,none,none,thin #333333"}); for (var i=1;i<50;i++) excel.set({row:i,style: i%2==0 ? evenRow: oddRow }); excel.set({row:3,value: 30 }); var headers=["Header 0","Header 1","Header 2","Header 3","Header 4"]; var formatHeader=excel.addStyle ( { border: "none,none,none,thin #333333",font: "Calibri 12 #0000AA B"} ); for (var i=0;i<headers.length;i++){ excel.set(0,i,0,headers[i],formatHeader); excel.set(0,i,undefined,"auto"); } var initDate = new Date(2000, 0, 1); var endDate = new Date(2016, 0, 1); var dStyle = excel.addStyle ( { align: "R", format: "yyyy.mm.dd hh:mm:ss", font: "#00AA00"} ); for (var i=1;i<50;i++){ excel.set(0,0,i,"This is line "+i); var d=randomDate(initDate,endDate); excel.set(0,1,i,d.toLocaleString()); excel.set(0,2,i,$JExcel.toExcelLocalTime(d)); excel.set(0,3,i,$JExcel.toExcelLocalTime(d),dStyle); excel.set(0,4,i,"Some other text"); } excel.set(0,1,undefined,30); excel.set(0,3,undefined,30); excel.set(0,4,undefined,20, excel.addStyle( {align:"R"})); excel.set(0,1,3,undefined,excel.addStyle( {align:"L T"})); excel.set(0,2,3,undefined,excel.addStyle( {align:"C C"})); excel.set(0,3,3,undefined,excel.addStyle( {align:"R B"})); excel.generate("SampleData.xlsx");
…generates the following Excel WorkBook:
Notice the different display in columns B,C & D, they basically hold the same data, but in different formats. Also, the different sizes and cell alignments all along row 4 is noticeable.
Formulas
To use a formula, just enter it as you would do in Excel:
excel.set(0,8,1,15); excel.set(0,8,2,13); excel.set(0,8,3,"=I2+I3");
Finally
Implementing this conversor was easier than expected. The code is short and well commented, and should be easily hackable for adding new capabilities (i.e., cell merging). You can find a demo on http://jsegarra1971.github.io/MyExcel/sample.html and the latest code is available at https://github.com/jsegarra1971/MyExcel
If you use it, let me know !!!
This member has not yet provided a Biography. Assume it’s interesting and varied, and probably something to do with programming.
Всем привет, в этой статье я покажу, как с помощью Excel можно формировать JS массивы на основе таблиц… Звучит как бред, однако в дальнейшем можно сохранить массив в js файл, изменить расширение файла на DB и полученную «базу данных» подключать к простой веб странице, можно использовать в Android приложении или расширении для браузера. Меняя содержимое файла можно изменять данные не затрагивая html код, и тут пригодится Excel, который возьмет на себя перевод данных из таблицы в массив. Разбор из файла в JSON будет происходить в веб странице.
Итак, сохраним книгу Excel с поддержкой макросов, работать будем с двумя листами, tab
— таблица и test
— лист с кнопкой и готовым результатом. В редакторе VBA добавим новый модуль, и внесем в него следующий код:
Sub main() Dim myCol, myRow As Integer Dim name1, name2 As String Dim namval myRow = 4 'строки myCol = 2 'столбцы name1 = "name" name2 = "age" namval = Sheets("tab").Range(Sheets("tab").Cells(1, 1), Sheets("tab").Cells(myRow, myCol)) For j = 1 To myRow Sheets("test").Cells(j, 1) = "{" & Chr(34) & name1 & Chr(34) & ":" & Chr(34) & namval(j, 1) & Chr(34) & "," & Chr(34) & name2 & Chr(34) & ":" & namval(j, 2) & "}," If j = myRow Then Sheets("test").Cells(j, 1) = "{" & Chr(34) & name1 & Chr(34) & ":" & Chr(34) & namval(j, 1) & Chr(34) & "," & Chr(34) & name2 & Chr(34) & ":" & namval(j, 2) & "}" End If Next j myRow = WorksheetFunction.CountA(Sheets("tab").Range("A:A")) 'строки myCol = WorksheetFunction.CountA(Sheets("tab").Range("A1:AAA1")) 'столбцы MsgBox "строки: " & myRow & " столбцы " & myCol End Sub
Привяжем кнопку к модулю и нажмем на нее. Полученные данные вставим в текстовый файл с текстом
var arr = [ //ваши данные ];
между кавычками. Файл сохраняем как JS, но с расширением db.
В секции head
веб страницы(я ипользовал bootstrap шаблон), добавим «базу данных» как если бы это был скрипт. Прим: при использовании уберите пробел перед левой кавычкой!
< script src="/test.db">< /script>
В секции body опишем таблицу для вывода данных и script
, который будет формировать строки и столбцы на странице. Прим: при использовании уберите пробел перед левой кавычкой!
< table class="table"> < thead> < tr> < th scope="col">Имя</th> < th scope="col">Возраст</th> < /tr> < /thead> < tbody> < script> for(x=0;x < arr.length;x++){ var serializedUser = JSON.stringify(arr[x]); var user = JSON.parse(serializedUser); document.write("< tr>< td>" + user.name + "< /td>< td>" + user.age + "< /td>< /tr>"); } < /script> < /tbody>< /table>
При запуске html страницы будет отображена таблица: заголовок Имя
и Возраст
и данные name
и age
.
Первый VBA модуль обладает одним недостатком: имена полей приходится указывать в коде и самих полей только два, данные начинаются с первой строки. Вторая версия модуля сама определяет имена полей и их количество, «шапка» таблицы в первой строке, данные начинаются со второй строки. Сделайте копии листов tab
, test
сохранив как tab2
, test2
, добавьте новый модуль, вставьте в него следующий код и присвойте кнопке Module2.
Sub main2() Dim myCol, myRow, namCount As Integer Dim name1, name2 As String Dim namval, nam Dim str0, str1, str2, str3, str4, mStr str0 = "{" & Chr(34) str1 = Chr(34) & ":" & Chr(34) str2 = Chr(34) & "," & Chr(34) str3 = "}," str4 = "}" 'myRow = 5 'строки 'myCol = 2 'столбцы myRow = WorksheetFunction.CountA(Sheets("tab2").Range("A:A")) 'строки myCol = WorksheetFunction.CountA(Sheets("tab2").Range("A1:AAA1")) 'столбцы namCount = WorksheetFunction.CountA(Sheets("tab2").Range("A1:N1")) 'количество столбцов namval = Sheets("tab2").Range(Sheets("tab2").Cells(2, 1), Sheets("tab2").Cells(myRow, myCol)) 'значения таблицы nam = Sheets("tab2").Range("A1:N1") 'шапка For j = 2 To myRow mStr = str0 For i = 1 To namCount mStr = mStr & nam(1, i) & str1 & namval(j - 1, i) & str2 Next i mStr = Left(mStr, Len(mStr) - 2) mStr = mStr & str3 Sheets("test2").Cells(j - 1, 1) = mStr If j = myRow Then mStr = str0 For i = 1 To namCount mStr = mStr & nam(1, i) & str1 & namval(j - 1, i) & str2 Next i mStr = Left(mStr, Len(mStr) - 2) mStr = mStr & str4 Sheets("test2").Cells(j - 1, 1) = mStr End If Next j End Sub
Данный код модуля позволяет автоматически определять количество строк и столбцов, названия заголовков шапки таблицы, которые будут впоследствии использованы для получаения данных. При этом код в html стрнице нормально работает и с русскими буквами: user.name
и user.Имя
распознаются одинаково.
На что еще хочу обратить внимание это кодировка страницы и файла «базы данных», они должны быть одинаковые, например UTF-8, для страницы указываем charset=utf8
, а файл test.db
сохраняем в Notepad++, иначе вместо текста получатся «кракозябры»….
Смотрите видео: База данных из JavaScript для веб страницы из Excel на VBA модуле.
Понравилась статья? Поделитесь ею с друзьями и напишите отзыв в комментариях!
От автора: очень часто при разработке веб-приложений возникает задача создать прайс-лист товаров либо услуг какой то кампании в формате таблиц Microsoft Excel. Но при этом необходимо предусмотреть, чтобы он свободно генерировался на основе данных, хранящихся в базе данных.
В сегодняшнем уроке мы с Вами решим такую задачу. То есть мы научимся генерировать документ в формате таблиц Excel при помощи языка PHP и специальной библиотеки PHPExcel. Это очень мощная и очень широко применяемая библиотека с огромнейшим функционалом. Конечно, все ее возможности за один урок рассмотреть мы не сможем, но узнать основы и научиться с ней работать — мы вполне успеем.
План урока
1. Подготовка к уроку.
2. Установка библиотеки PHPExcel.
3. Основные настройки листа книги Excel.
4. Наполнение документа данными.
5. Стилизация данных.
Детали учебника
Тема: PHP
Сложность: Средняя
Урок: Видео (.mp4)
Время: 01:31:02
Размер архива: 217 Mb
1. Подготовка к уроку.
Первое что нам потребуется для создания прайс-листа – это данные, которые в нем выводить. Для этого я подготовил базу данных (под названием price), в которой содержится всего одна табличка – tovar. В табличке содержится несколько наименований товара, для вывода в прайс-листе. Ее дамп Вы сможете взять из изходников к уроку.
Далее я подготовил очень простой скрипт, который вытаскивает данные из базы данных, а конкретнее из таблички tovar, и формирует из этих данных массив. С этим массивом мы с Вами и будем работать.
Скрипт включает в себя всего три файла:
config.php
functions.php
index.php
Важное замечание!
Если Вы хотите использовать для вывода данных в формате EXCEL русские символы, то обязательно все файлы нужно сохранять в кодировке UTF8.
Далее давайте приведу код всех трех файлов. Файл config.php:
<?php define(«HOST»,«localhost»); define(«USER»,«Viktor»); define(«PASSWORD»,«1234»); define(«DB»,«price»); $db = mysql_connect(HOST,USER,PASSWORD); if (!$db) { exit(‘WRONG CONNECTION’); } if(!mysql_select_db(‘price’,$db)) { exit(DB); } mysql_query(‘SET NAMES utf8’); ?> |
Как Вы видите, здесь все элементарно. Просто задаем четыре константы для хранения настроек подключения к базе данных. И собственно, выполняем подключение и выбор базы данных для работы. Далее устанавливаем кодировку запросов.
Следующий файл functions.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php function get_price() { $sql = «SELECT id,name,price,quantity FROM tovar»; $result = mysql_query($sql); if(!$result) { exit(mysql_error()); } $row = array(); for($i = 0;$i < mysql_num_rows($result);$i++) { $row[] = mysql_fetch_assoc($result); } return $row; } |
Здесь также все очень просто. Описана всего лишь одна функция, которая выполняет запрос к базе данных и формирует по результатам выборки массив. Далее я приведу распечатку этого массива.
И последний файл index.php:
<?php require_once ‘config.php’; require_once ‘functions.php’; $price_list = get_price(); ?> |
В этом файле мы дальше будем вести все кодирование. Это пока лишь заготовка. Как Вы видите, вначале я подключаю файлы config.php и functions.php и вызываю функцию get_price(), для получения массива товаров.
Давайте я приведу распечатку этого массива (при помощи функции print_r()):
Теперь, думаю, Вам понятно, что содержится в массиве $price_list. Теперь перейдем к установке библиотеки PHPExcel.
2. Установка библиотеки PHPExcel.
Первым делом библиотеку необходимо скачать. Для этого переходим на официальный сайт библиотеки — //phpexcel.codeplex.com/ :
И нажимаем по кнопке download. В результате скачивания у нас получится архив PHPExcel-1.7.7.zip. Давайте его распакуем. Как Вы видите, после распаковки у нас получилось несколько файлов и папок:
Classes
Documentation
Tests
changelog.txt
install.txt
license.txt
Файлы — это различные описания по предыдущим версиям, лицензионное соглашение и очень краткая инструкция по установке. Далее в папке Classes, содержится непосредственно сама библиотека PHPExcel – эту папку необходимо скопировать в корень нашего скрипта, что я и сделал.
В папке Documentation – содержится документация по библиотеке, но правда она на английском языке. Но все равно я Вам рекомендую с ней ознакомиться. Так как библиотека имеет огромнейший функционал, и конечно сегодня мы весь его не рассмотрим. А в документации Вы найдете много всего интересного.
В папке Tests – содержатся примеры по использованию библиотеки.
Итак, если Вы скопировали папку Classes в корень скрипта, то мы можем приступать к дальнейшей работе.
Итак, переходим в файл index.php и начинаем работать с ним. Теперь нам необходимо подключить главный файл библиотеки PHPExcel.php (который находится в папке Classes) к нашему скрипту и создать объект класса PHPExcel:
require_once ‘Classes/PHPExcel.php’; $objPHPExcel = new PHPExcel(); |
Для тех кто не знает класс – это своего рода чертеж или описательный элемент, какой то определенной сущности. То есть в нашем случае (если сказать простыми словами) класс PHPExcel.php описывает все методы (это обычные функции, только описанные в классе) и свойства (переменные класса) необходимые для вывода данных в формате Excel.
Для того что бы создать объект класса необходимо указать переменную ($objPHPExcel) затем поставить знак присвоения, далее ключевое слово new и указать имя класса. Объект – это такой тип переменной, который позволяет нам работать с методами и свойствами класса. То есть если мы создали объект, то мы получили доступ ко всему, что описано в классе.
На этом установка библиотеки завершена, можно приступать к работе с ней.
3. Основные настройки листа книги Excel.
Как Вы знаете, документ Excel состоит из книг, а каждая книга в свою очередь, состоит из листов. Далее лист состоит из набора ячеек, доступ к которым осуществляется по координатам. То есть у нас есть столбцы, которые имеют буквенные имена (А, В, С и т.д) и есть строки, которые пронумерованы. Значит, что бы получить доступ к первой ячейке нужно указать код А1. Точно также мы с помощью библиотеки будем получать доступ к каждой ячейке.
Итак, первым делом необходимо выбрать активный лист, на который мы будем выводить данные и получить объект этого листа.
$objPHPExcel—>setActiveSheetIndex(0); $active_sheet = $objPHPExcel—>getActiveSheet(); |
С помощью метода setActiveSheetIndex(0) – указываем индекс (номер) активного листа. Нумерация листов начинается с нуля. Далее с помощью метода getActiveSheet() – получаем объект этого активного листа, то есть другими словами получаем доступ к нему для работы. И сохраняем этот объект в переменную $active_sheet.
Если Вы захотите указать активным какой то другой лист, то вначале его необходимо создать, при помощи метода:
$objPHPExcel—>createSheet(); |
Затем по аналогии, указываем индекс и получаем объект активного листа.
Теперь давайте сгенерируем наш первый документ Excel (правда конечно пока пустой), для этого в файл index.php в его конец добавим следующий код (далее весь код, который я буду приводить, следует вставлять перед этим кодом – то есть код который идет ниже должен быть в самом низу файла – это уже завершение скрипта!!!):
header(«Content-Type:application/vnd.ms-excel»); header(«Content-Disposition:attachment;filename=’simple.xls'»); $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, ‘Excel5’); $objWriter—>save(‘php://output’); exit(); |
В начале, обратите внимание, отправляем заголовки.
Первый – указываем браузеру тип открываемого контента – это документ формата Excel. И второй – указываем браузеру, что документ необходимо отдать пользователю на скачивание и тут же указываем имя скачиваемого файла (‘simple.xls’ ).
Далее документ необходимо сохранить. Сначала нужно указать, в какой версии мы его сохраняем. Для этого у класса PHPExcel_IOFactory вызываем метод createWriter() и передаем ему объект $objPHPExcel и указываем версию Excel5. При этом будет создан объект класса PHPExcel_Writer_Excel5 и у него вызываем метод save(). Этому методу передаем параметром строку ‘php://output’, это означает, что файл не будет сохранен, а будет отдан браузеру, а браузер в свою очередь, отдаст его нам на скачивание.
Теперь немного о версиях. Кроме версии Excel5, доступна также версия Excel2007, но так как у меня установлен MS Office 2003, то версия Excel2007 у меня просто не откроется. Поэтому я создаю документ версии Excel5.
Теперь давайте перейдем в браузер и посмотрим, что у нас получилось:
Как Вы видите, мы с Вами получили пустой документ в формате Excel, с одним активным листом.
Теперь давайте пропишем остальные настройки листа (обратите внимание, что все методы мы вызываем у объекта $active_sheet – объекта активного листа документа и весь код вставляем перед заголовками – функция header):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//Ориентация страницы и размер листа $active_sheet—>getPageSetup() —>setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT); $active_sheet—>getPageSetup() —>SetPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4); //Поля документа $active_sheet—>getPageMargins()—>setTop(1); $active_sheet—>getPageMargins()—>setRight(0.75); $active_sheet—>getPageMargins()—>setLeft(0.75); $active_sheet—>getPageMargins()—>setBottom(1); //Название листа $active_sheet—>setTitle(«Прайс-лист»); //Шапа и футер $active_sheet—>getHeaderFooter()—>setOddHeader(«&CШапка нашего прайс-листа»); $active_sheet—>getHeaderFooter()—>setOddFooter(‘&L&B’.$active_sheet—>getTitle().‘&RСтраница &P из &N’); //Настройки шрифта $objPHPExcel—>getDefaultStyle()—>getFont()—>setName(‘Arial’); $objPHPExcel—>getDefaultStyle()—>getFont()—>setSize(8); |
Итак, вначале задаем ориентацию листа, при помощи метода setOrientation(), которому передаем константу, ORIENTATION_PORTRAIT, класса PHPExcel_Worksheet_PageSetup. Эта константа — означает, что ориентация страницы будет портретом.
Если Вы хотите расположить лист в виде альбомного листа, нужно методу setOrientation(), передать константу Worksheet_PageSetup::ORIENTATION_LANDSCAPE.
Обратите внимание, что перед методом setOrientation() необходимо вызвать метод getPageSetup() – который предоставит нам доступ к настройкам страницы (вернет объект класса, который отвечает за настройки страницы).
Далее вызываем метод SetPaperSize(), который позволяет задать размер страницы, для печати. Ему передаем параметром константу PAPERSIZE_A4, класса — PHPExcel_Worksheet_PageSetup. Что означает, что размер листа страницы будет установлен А4.
Это можно проверить, если открыть документ, в формате Excel и перейти в меню Файл, затем на пункт параметры страницы.
Далее устанавливаем поля документа, то есть отступы от краев документа. Отступы задаются в специальных символьных единицах. Вначале, обратите внимание, вызываем у объекта $active_sheet, метод getPageMargins() (он вернет объект класса, который отвечает за настройки полей страницы). Затем вызываем метод setTop(1), который задает верхний отступ страницы.
Далее по аналогии методы setRight(0.75), setLeft(0.75), setBottom(1) – задают соответственно правый, левый и нижний отступы документа.
Далее давайте при помощи метода setTitle(«Прайс лист») – зададим название нашего листа.
Затем при печати (если кому это нужно), можно выводить шапку и нижний футер листа. Такую возможность можно задать при помощи методов setOddHeader(«&CШапка нашего прайс-листа») и setOddFooter(‘&L&B’.$active_sheet->getTitle().’&RСтраница &P из &N’), которые задают соответственно — шапку и футер документа.
Обратите внимание на передаваемые параметры:
Для шапки – передаем строку — &C Шапка нашего прайс-листа (метка &C – означает, что текст нужно расположить по центру).
Для футера – передаем строку — &L&B’.$active_sheet->getTitle().’&RСтраница &P из &N’, это означает, что нужно вывести слева и жирным шрифтом (&L&B’), название листа (метод $active_sheet->getTitle()), затем справа (&R) вывести номер страницы (Страница &P) из общего количества страниц (&N).
Полный список меток, можно посмотреть в документации. Я этот список Вам не привожу, так как он очень большой, да и многие из них Вам не понадобятся.
Затем указываем настройки шрифта по умолчанию. Это можно сделать при помощи последовательного вызова методов:
$objPHPExcel->getDefaultStyle()->getFont()->setName(‘Arial’) – задаем имя шрифта;
$objPHPExcel->getDefaultStyle()->getFont()->setSize(8); — задаем размер шрифта;
Теперь если сохранить изменения и сгенерировать наш документ, то можно увидеть что у нас изменилось название листа документа на Прайс-лист, и если открыть предварительный просмотр страницы, то можно увидеть как выводится шапка и футер документа.
4. Наполнение документа данными
Для начала давайте зададим ширину основных столбцов, которые нам понадобятся:
$active_sheet—>getColumnDimension(‘A’)—>setWidth(7); $active_sheet—>getColumnDimension(‘B’)—>setWidth(80); $active_sheet—>getColumnDimension(‘C’)—>setWidth(10); $active_sheet—>getColumnDimension(‘D’)—>setWidth(10); |
Как вы видите вначале обращаемся к нашему объекту активного листа, далее вызываем метод getColumnDimension(‘A’) – то есть получаем доступ ширине столбца А (либо любого другого столбца, какой мы передадим методу параметром), затем задаем ширину, при помощи метода setWidth(ширина столбца) и передаем ему ширину в символьных единицах.
Для остальных столбцов – все аналогично.
Давайте посмотрим, что получилось:
Как Вы видите, размеры столбцов изменились. Теперь давайте заполним несколько ячеек текстом:
$active_sheet—>mergeCells(‘A1:D1’); $active_sheet—>getRowDimension(‘1’)—>setRowHeight(40); $active_sheet—>setCellValue(‘A1’,‘Техно мир’); $active_sheet—>mergeCells(‘A2:D2’); $active_sheet—>setCellValue(‘A2’,‘Компьютеы и комплектующие на любой вкус и цвет’); $active_sheet—>mergeCells(‘A4:C4’); $active_sheet—>setCellValue(‘A4’,‘Дата создания прайс-листа’); |
В начале давайте объединим ячейки с А1 до D1, при помощи метода mergeCells(диапазон ячеек) – который позволяет объединять ячейки.
Далее зададим высоту этих объединенных ячеек (строка 1), при помощи методов getRowDimension(‘1’)->setRowHeight(40) – смотрите, вначале получаем доступ к строке 1 (getRowDimension(‘1’)), затем задаем высоту (setRowHeight(высота строки)).
И затем при помощи метода setCellValue(‘A1′,’Техно мир’), устанавливаем значение ячейки А1. Этот метод позволяет записать данные в любую ячейку. Координаты ячейки передаем первым параметром, а значение – вторым.
Следующие ячейки заполняем по аналогии. Давайте посмотрим, что у нас получилось:
Далее давайте в ячейку D4 запишем текущую дату:
//Записываем данные в ячейку $date = date(‘d-m-Y’); $active_sheet—>setCellValue(‘D4’,$date); //Устанавливает формат данных в ячейке — дата $active_sheet—>getStyle(‘D4’) —>getNumberFormat() —>setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14); |
Для этого запишем текущую дату в ячейку D4, а затем установим формат данных этой ячейки – как дата. Для этого необходимо последовательно вызвать методы у объекта $active_sheet:
getStyle(‘D4’)—>getNumberFormat()—> setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14); |
То есть получаем доступ к стилям ячейки D4 ( метод getStyle(‘D4’) вернет объект класса отвечающий за стили ячейки), затем получаем формат данных этой ячейки и устанавливаем новый формат данных (setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14)).
В константе FORMAT_DATE_XLSX14 хранится строка с форматом даты (вида дд-мм-гггг). Все константы, относящиеся к форматам даты можно посмотреть в документации по библиотеке.
Теперь, используя метод setCellValue(), а также цикл foreach() давайте наполним данными наш прайс-лист:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//Создаем шапку таблички данных $active_sheet—>setCellValue(‘A6’,‘№п.п’); $active_sheet—>setCellValue(‘B6’,‘Имя’); $active_sheet—>setCellValue(‘C6’,‘Цена’); $active_sheet—>setCellValue(‘D6’,‘кол-во’); //В цикле проходимся по элементам массива и выводим все в соответствующие ячейки $row_start = 7; $i = 0; foreach($price_list as $item) { $row_next = $row_start + $i; $active_sheet—>setCellValue(‘A’.$row_next,$item[‘id’]); $active_sheet—>setCellValue(‘B’.$row_next,$item[‘name’]); $active_sheet—>setCellValue(‘C’.$row_next,$item[‘price’]); $active_sheet—>setCellValue(‘D’.$row_next,$item[‘quantity’]); $i++; } |
Теперь давайте сохраним изменения и посмотрим, что получилось:
Как Вы видите, данные успешно вывелись.
5. Стилизация данных.
Теперь давайте красиво украсим наш прайс-лист, то есть каждой ячейке добавим стилей. Для этого необходимо создать массив со стилями (стили очень похожи на правила CSS), и при помощи метода applyFromArray($массив стилей), применить этот массив к ячейке:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//массив стилей $style_wrap = array( //рамки ‘borders’=>array( //внешняя рамка ‘outline’ => array( ‘style’=>PHPExcel_Style_Border::BORDER_THICK ), //внутренняя ‘allborders’=>array( ‘style’=>PHPExcel_Style_Border::BORDER_THIN, ‘color’ => array( ‘rgb’=>‘696969’ ) ) ) ); //применяем массив стилей к ячейкам $active_sheet—>getStyle(‘A1:D’.($i+6))—>applyFromArray($style_wrap); |
Обратите внимание, как необходимо оформлять массив стилей. Вначале идет главный массив с ключом – главное правило (к примеру borders – рамки), а в нем еще массивы с правилами. Стили для каждого правила (для каждого вида рамки) – это константы. К примеру, BORDER_THICK – это жирная рамка, BORDER_THIN – это тоненькая рамка.
После создания массива вызываем методы getStyle() – для получения объекта класса, отвечающего за стили выбранной ячейки, а затем метод applyFromArray($style_wrap), который применяет массив стилей к ячейке.
Обратите внимание, как я указал диапазон ячеек в методе getStyle(‘A1:D’.($i+6)). Переменная $i – это число итераций цикла, который выводит данные из массива. А число 6 – это количество строк до вывода данных из цикла. Давайте перейдем в браузер и посмотрим, что получилось:
Как Вы видите, стили успешно применились. Теперь давайте по аналогии, применим стили к остальным ячейкам:
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
//Стили для верхней надписи строка 1 $style_header = array( //Шрифт ‘font’=>array( ‘bold’ => true, ‘name’ => ‘Times New Roman’, ‘size’ => 20 ), //Выравнивание ‘alignment’ => array( ‘horizontal’ => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_CENTER, ‘vertical’ => PHPExcel_STYLE_ALIGNMENT::VERTICAL_CENTER, ), //Заполнение цветом ‘fill’ => array( ‘type’ => PHPExcel_STYLE_FILL::FILL_SOLID, ‘color’=>array( ‘rgb’ => ‘CFCFCF’ ) ) ); $active_sheet—>getStyle(‘A1:D1’)—>applyFromArray($style_header); //Стили для слогана компании – вторая строка $style_slogan = array( //шрифт ‘font’=>array( ‘bold’ => true, ‘italic’ => true, ‘name’ => ‘Times New Roman’, ‘size’ => 13, ‘color’=>array( ‘rgb’ => ‘8B8989’ ) ), //выравнивание ‘alignment’ => array( ‘horizontal’ => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_CENTER, ‘vertical’ => PHPExcel_STYLE_ALIGNMENT::VERTICAL_CENTER, ), //заполнение цветом ‘fill’ => array( ‘type’ => PHPExcel_STYLE_FILL::FILL_SOLID, ‘color’=>array( ‘rgb’ => ‘CFCFCF’ ) ), //рамки ‘borders’ => array( ‘bottom’ => array( ‘style’=>PHPExcel_Style_Border::BORDER_THICK ) ) ); $active_sheet—>getStyle(‘A2:D2’)—>applyFromArray($style_slogan); //Стили для текта возле даты $style_tdate = array( //выравнивание ‘alignment’ => array( ‘horizontal’ => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_RIGHT, ), //заполнение цветом ‘fill’ => array( ‘type’ => PHPExcel_STYLE_FILL::FILL_SOLID, ‘color’=>array( ‘rgb’ => ‘CFCFCF’ ) ), //рамки ‘borders’ => array( ‘right’ => array( ‘style’=>PHPExcel_Style_Border::BORDER_NONE ) ) ); $active_sheet—>getStyle(‘A4:C4’)—>applyFromArray($style_tdate); //Стили для даты $style_date = array( //заполнение цветом ‘fill’ => array( ‘type’ => PHPExcel_STYLE_FILL::FILL_SOLID, ‘color’=>array( ‘rgb’ => ‘CFCFCF’ ) ), //рамки ‘borders’ => array( ‘left’ => array( ‘style’=>PHPExcel_Style_Border::BORDER_NONE ) ), ); $active_sheet—>getStyle(‘D4’)—>applyFromArray($style_date); //Стили для шапочки прайс-листа $style_hprice = array( //выравнивание ‘alignment’ => array( ‘horizontal’ => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_CENTER, ), //заполнение цветом ‘fill’ => array( ‘type’ => PHPExcel_STYLE_FILL::FILL_SOLID, ‘color’=>array( ‘rgb’ => ‘CFCFCF’ ) ), //Шрифт ‘font’=>array( ‘bold’ => true, ‘italic’ => true, ‘name’ => ‘Times New Roman’, ‘size’ => 10 ), ); $active_sheet—>getStyle(‘A6:D6’)—>applyFromArray($style_hprice); //стили для данных в таблице прайс-листа $style_price = array( ‘alignment’ => array( ‘horizontal’ => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_LEFT, ) ); $active_sheet—>getStyle(‘A7:D’.($i+6))—>applyFromArray($style_price); |
Теперь давайте посмотрим на окончательный результат нашей работы:
Вот так вот выглядит окончательный вариант нашего прайс-листа. Согласитесь очень достойный вид. Притом, что мы не затратили на его создание очень много времени. Еще раз Вам рекомендую просмотреть документацию по библиотеке PHPExcel, там содержится очень много всего интересного.
На этом у меня все. Удачного Вам кодирования и до новых встреч!
Уровень сложности
Средний
Время на прочтение
9 мин
Количество просмотров 14K
Работая в IoT-сфере и плотно взаимодействуя с одним из основных элементов данной концепции технологий – сетевым сервером, столкнулся вот с какой проблемой (задачей): необходимо отправлять много запросов для работы с умными устройствами на сетевой сервер. На сервере был реализован REST API с оболочкой Swagger UI, где из графической оболочки можно было отправлять только разовые запросы. Анализ сторонних клиентов, типа Postman или Insomnia показал, что простого визуального способа поместить в скрипт массив из необходимого перечня идентификаторов устройств (или любых других элементов сервера), для обращения к ним – не нашлось.
Так как большая часть работы с выгрузками и данными была в Excel, то решено было вспомнить навыки, полученные на учебе в университете, и написать скрипт на VBA, который бы мою задачку решал.
Необходимо было:
-
получать информацию по устройствам с различными параметрами фильтрации (GET);
-
применять изменения в конфигурации по устройствам: имя, профиль устройства, сетевые лицензии и пр. (PUT);
-
отправлять данные для конфигурации и взаимодействия с устройствами (POST).
И сегодня я расскажу вам про то, как с помощью Excel, пары формул и самописных функций на VBA можно реализовать алгоритм, отправляющий любое необходимое количество REST-API запросов с использованием авторизации Bearer Token.
Данная статья будет полезная тем, кто воспользуется данным решением под Windows, но еще больше она будет полезна тем людям, которые хотят использовать данное решение на MacOS (с Excel x64) . Как вы уже догадались, ниже будут рассмотрены два варианта реализации под разные системы, так как с MacOS есть нюанс.
Часть 1. Реализация решения под Windows
GET
Начнем с самого простого: GET – запросов. В данном примере необходимо получить ответ (информацию) от сервера по заданному списку устройств.
Для реализации GET – запросов нам дано:
1) Ссылка, в которой указываются параметры запроса.
https://dx-api.thingpark.io/core/latest/api/devices?deviceEUI=
2) Заголовки запроса + Токен авторизации (Bearer Token)
—header ‘Accept: application/json’ —header ‘Authorization: Bearer
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJTVUJTQ1JJQkVSOjY3MDAiXSwiZXhwIjozNzc0MTY0MzE4LCJqdGkiOiI5OTNiOTk1Ny03NGY1LTQ5MDgtYjg4Ni0xYjk5NTVkZDQwZTEiLCJjbGllbnRfaWQiOiJkZXYxLWFwaS9lcnRoLnRlY2guZGVzayt2bGFkaXNsYXYuZ2F0Y2Vua29AZ21haWwuY29tIn0.dqybsMdVXXpQV8_ykufNZoQpSPZrVA67uieOJan-qs8W7rAImyy0552buniHXPWy6ilvdwJKPCdIKE__LghP6A
3) Параметр, указываемый в ссылке (в данном примере это идентификаторы устройств – DevEUI):
1ABCDEFF00AABBCC
0016ACC4DCF15A23
D88039FFFE954DF4
0000000000001103
0000000000001104
Имея такие данные на входе, делаем в Excel лист-шаблон, который заполняем в соответствии с тем, что имеем:
-
столбец А уходит вот значения параметров
-
столбец F уходит под ссылку-родителя
-
столбец H уходит под заголовки, где в ячейке H1 единоразово для текущего листа указывается токен:
=СЦЕП("--header 'Accept: application/json' --header 'Authorization: Bearer ";$H$1;"'")
-
столбец I уходит под URL (ссылки-дети, на основе ссылки-родителя)
=СЦЕПИТЬ($F$1;A2)
-
столбец J уходит под результат (ответ от сервера)
Далее, нам необходимо реализовать подпрограмму(макрос) отправки GET-запросов. Состоит она из четырех частей:
-
цикла, который считает количество строк для работы по листу, пробегая по столбцу А с 2 по первую пустую ячейку, чтобы у цикла был конец.
-
функции, для работы с REST API (используется стандартная, библиотека Msxml2.XMLHTTP.6.0, встроенная в Windows., поэтому сложностей с реализацией не возникает. Для MacOS есть альтернатива)
-
временной задержки, в случае если нужно отправлять запросы не сразу, после получения ответа, а задав время ожидания
-
таймером, который показывает время выполнения всего макроса после завершения
Код:
Sub GET_Request() Dim i As Integer Dim j As Integer Dim objHTTP As Object Dim Json As String Dim result As String Dim URL As String Dim Token As String a = Timer i = 1 Do While Not IsEmpty(Cells(i, 1)) i = i + 1 Loop i = i - 1 'MsgBox i For j = 2 To i Json = Range("D" & j) URL = Range("I" & j) Token = Range("H1") Set objHTTP = CreateObject("Msxml2.XMLHTTP.6.0") objHTTP.Open "GET", URL, False objHTTP.setRequestHeader "Content-type", "application/json" objHTTP.setRequestHeader "Accept", "application/json" objHTTP.setRequestHeader "Authorization", "Bearer " + Token objHTTP.Send (Json) result = objHTTP.responseText Range("J" & j).Value = result Set objHTTP = Nothing 'Application.Wait (Now + TimeValue("0:00:01")) Next j MsgBox Timer - a End Sub
Привязываем подпрограмму к кнопкам для удобства и выполним скрипт. Получается:
Таким образом, скрипт проходит по столбцу I, забирая из значения каждой ячейки URL, для тех строк, где в столбце А есть значения (которые и подставляются в URL). Для удобства также сделаны кнопки очистки полей и подсветка запросов условным форматированием, в случае успешного ответа на запрос.
PUT
Чуть-чуть усложним задачу и перейдем к PUT-запросам. В данном примере необходимо изменить профиль устройства, чтобы сервер по-другому с ним взаимодействовал.
К исходным данным для GET – запроса добавляется тело запроса с ключем-значением (п4). Итого дано:
1) Ссылка, в которой указываются параметры запроса.
https://dx-api.thingpark.io/core/latest/api/devices/
2) Заголовки запроса + Токен авторизации (Bearer Token)
—header ‘Content-Type: application/json’ —header ‘Accept: application/json’ —header ‘Authorization: Bearer
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJTVUJTQ1JJQkVSOjY3MDAiXSwiZXhwIjozNzc0MTY0MzE4LCJqdGkiOiI5OTNiOTk1Ny03NGY1LTQ5MDgtYjg4Ni0xYjk5NTVkZDQwZTEiLCJjbGllbnRfaWQiOiJkZXYxLWFwaS9lcnRoLnRlY2guZGVzayt2bGFkaXNsYXYuZ2F0Y2Vua29AZ21haWwuY29tIn0.dqybsMdVXXpQV8_ykufNZoQpSPZrVA67uieOJan-qs8W7rAImyy0552buniHXPWy6ilvdwJKPCdIKE__LghP6A
3) Параметр, указываемый в ссылке (в данном примере это внутренние идентификаторы устройств – hRef):
17272
18199
17242
17245
17248
4) Тело запроса, с ключом и значением:
{«deviceProfileId»:»LORA/GenericA.1.0.3a_ETSI»}
Немного дополняем новый PUT-лист в Excel по сравнению с GET (остальное без изменений):
-
новый столбец B теперь отвечает за ключ deviceProfileId (ячейка B1), а все значения ниже за его возможные значения)
-
столбец D отвечает за формирование итогового тела сообщения в формате JSON.
=СЦЕПИТЬ("'{""";$B$1;""":""";B2;"""";"}'")
Немного поменяем макрос и вынесем его в отдельную подпрограмму:
Код:
Sub PUT_Request()
Dim i As Integer
Dim j As Integer
Dim objHTTP As Object
Dim Json As String
Dim result As String
Dim URL As String
Dim Token As String
a = Timer
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'MsgBox i
For j = 2 To i
Json = Range("D" & j)
URL = Range("I" & j)
Token = Range("H1")
Set objHTTP = CreateObject("Msxml2.XMLHTTP.6.0")
objHTTP.Open "PUT", URL, False
objHTTP.setRequestHeader "Content-type", "application/json"
objHTTP.setRequestHeader "Accept", "application/json"
objHTTP.setRequestHeader "Authorization", "Bearer " + Token
objHTTP.Send (Json)
result = objHTTP.responseText
Range("J" & j).Value = result
Set objHTTP = Nothing
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
Привяжем макрос к кнопке и выполним.
Логика абсолютно аналогична GET запросу.
POST
Для POST запросов все аналогично PUT. Только немного меняется код в части типа запроса. В данном примере на устройство отправляется команда-конфигурация с указанием тела посылки (payload_hex) и порта (fport) для конкретного устройства.
Код:
Sub PUT_Request()
Dim i As Integer
Dim j As Integer
Dim objHTTP As Object
Dim Json As String
Dim result As String
Dim URL As String
Dim Token As String
a = Timer
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'MsgBox i
For j = 2 To i
Json = Range("D" & j)
URL = Range("I" & j)
Token = Range("H1")
Set objHTTP = CreateObject("Msxml2.XMLHTTP.6.0")
objHTTP.Open "PUT", URL, False
objHTTP.setRequestHeader "Content-type", "application/json"
objHTTP.setRequestHeader "Accept", "application/json"
objHTTP.setRequestHeader "Authorization", "Bearer " + Token
objHTTP.Send (Json)
result = objHTTP.responseText
Range("J" & j).Value = result
Set objHTTP = Nothing
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
Получившаяся таблица выглядит следующим образом:
На этом часть для Windows заканчивается. Здесь все оказалось довольно просто: стандартная библиотека, простенький алгоритм перебора значений в цикле.
Часть 2. Реализация решения под MacOS и Excel 64-bit
В виду того, что работал я на двух машинах под управлением разных ОС, хотелось, чтобы решение было универсальным. В итоге, собрав по крупицам информацию по интернет-форумам с данной тематикой у меня вышло следующее решение. Принцип работы его остается схожим, а изменения были внесены в часть, где использовалась стандартная библиотека WindowsMsxml2.XMLHTTP.6.0, которой в MacOS не было по понятным причинам.
Чтобы обойти данное ограничение, был выбран единственный рабочий подход через cUrl, exec и функции. Данное решение точно работает под версией MacOS 10.14 и Excel 16.51. Функция ниже, в том или ином виде, встречается на различных форумах, однако на текущих версиях софта – не работает. В итоге, после небольших правок получили рабочий вариант:
Была отлажена функция вызова ExecShell:
Код:
Option Explicit
Private Declare PtrSafe Function popen Lib "/usr/lib/libc.dylib" (ByVal Command As String, ByVal Mode As String) As LongPtr
Private Declare PtrSafe Function pclose Lib "/usr/lib/libc.dylib" (ByVal file As LongPtr) As Long
Private Declare PtrSafe Function fread Lib "/usr/lib/libc.dylib" (ByVal outStr As String, ByVal size As LongPtr, ByVal items As LongPtr, ByVal stream As LongPtr) As Long
Private Declare PtrSafe Function feof Lib "/usr/lib/libc.dylib" (ByVal file As LongPtr) As LongPtr
Function execShell(Command As String, Optional ByRef exitCode As Long) As String
Dim file As LongPtr
file = popen(Command, "r")
If file = 0 Then
Exit Function
End If
While feof(file) = 0
Dim chunk As String
Dim read As Long
chunk = Space(500)
read = fread(chunk, 1, Len(chunk) - 1, file)
If read > 0 Then
chunk = Left$(chunk, read)
execShell = execShell & chunk
End If
Wend
exitCode = pclose(file)
End Function
И написаны отдельные функции для работы с различным методами GET / PUT / POST, которые на входе принимают URL и параметры):
Код:
Function HTTPGet(sUrl As String, sQuery As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl -X GET " & sQuery & "" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
HTTPGet = sResult
End Function
Function HTTPPost(sUrl As String, sQuery1 As String, sQuery2 As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl -X POST " & sQuery1 & "" & " -d " & sQuery2 & "" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
HTTPPost = sResult
End Function
Function HTTPPut(sUrl As String, sQuery1 As String, sQuery2 As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl -X PUT " & sQuery1 & "" & " -d " & sQuery2 & "" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
HTTPPut = sResult
End Function
Так как мы заменяем библиотеку Msxml2.XMLHTTP.6.0 – поменялась реализация макросов в этой части: мы заменили Msxml2 на написанные выше функции и получили следующее:
Код:
'GET-запросы
Sub SendGETRequest()
Dim i As Integer
Dim j As Integer
Dim result As String
Dim URL As String
Dim Auth As String
a = Timer
'Подсчет заполненных ячеек первого столбца
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'Цикл, который отправляет запрос от 2 до последнего элемента
For j = 2 To i
URL = Range("I" & j)
Auth = Range("H" & j)
result = HTTPGet(URL, Auth)
Range("J" & j).Value = result
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
'PUT-запросы
Sub SendPUTRequest()
Dim i As Integer
Dim j As Integer
Dim result As String
Dim URL As String
Dim Auth As String
Dim Message As String
a = Timer
'Подсчет заполненных ячеек первого столбца
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'Цикл, который отправляет запрос от 2 до последнего элемента
For j = 2 To i
Message = Range("D" & j)
URL = Range("I" & j)
Auth = Range("H" & j)
result = HTTPPut(URL, Auth, Message)
Range("J" & j).Value = result
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer - a
End Sub
'POST-запросы
Sub SendPOSTRequest()
Dim i As Integer
Dim j As Integer
Dim result As String
Dim URL As String
Dim Auth As String
Dim Message As String
a = Timer
'Подсчет заполненных ячеек первого столбца
i = 1
Do While Not IsEmpty(Cells(i, 1))
i = i + 1
Loop
i = i - 1
'Цикл, который отправляет запрос от 2 до последнего элемента
For j = 2 To i
Message = Range("D" & j)
URL = Range("I" & j)
Auth = Range("H" & j)
result = HTTPPost(URL, Auth, Message)
Range("J" & j).Value = result
'Application.Wait (Now + TimeValue("0:00:01"))
Next j
MsgBox Timer – a
Итог
В итоге, у меня получилось аналогичное windows по работе и функционалу решение для MacOS c использованием Excel 64-bit.
На просторах интернета я не нашел какого-то сборного и единого описания, только фрагменты кода и подходов, которые в большинстве случаев не работали полностью или частично. Поэтому решил объединить все в рабочее решение и выложить на хабр для истории.
На текущий момент я все еще не встретил иного решения, которое бы позволяло в пару кликов копипастить тысячи идентификаторов и параметров из excel и массово их отправлять на сервер. Надеюсь, кому-то пригодится
Если такие сторонние решения есть, а я не в курсе, и все можно было сделать проще, быстрее и изящнее – делитесь опытом в комментариях.
Примечание:
Файл-пример, который можно потыкать, пока жив сервер и «бессрочный» токен:
https://disk.yandex.ru/d/y7EVtn8afM4QPg
Открытое описание API, если кому-то будет любопытно
Снова используем OneDrive и Google Диск. Таблица внедряется на сайт через элемент <iframe>. Корректное отображение контейнера в <iframe> зависит от версии языка разметки вашей страницы — <!DOCTYPE>.
OneDrive — Microsoft
Заходим в OneDrive (требуется авторизация или регистрация). Добавляем файл электронной таблицы. Открываем.
Далее, Файл → Общий доступ → Внедрить.
Настройки и размер по вкусу. Копируем на выбор код внедрения или код JavaScript — вставляем в нужное место страницы.
Пример.
Google Диск — Документы
Заходим в Google Диск (требуется авторизация или регистрация). Добавляем файл электронной таблицы. Открываем через Google Таблицы.
Далее, Файл → Опубликовать в Интернете → Встроить.
Копируем и вставляем код в нужное место страницы.
Пример.