Салют! На связи Ганзюк Владимир. Тружусь инженером по нормативно-справочной информации (НСИ) в компании Bimeister.

Хочу поделиться с вами опытом работы с Excel и рассказать, как можно ускорить выполнение рутинных задач при работе с составлением наименований согласно нормативно-технической документации (НТД).

От простого к сложному

Терпения… Автоматизация при помощи VBA начнется чуть позже, а сейчас я хочу рассказать, как при помощи обычного выпадающего списка можно повысить эффективность работы в Excel.

Суть работы:

Имеем шаблон с проработанными данными для загрузки в систему. Проработка шаблона включает в себя множество рутинных задач:

  • Ввод однотипных наименований материалов в шаблон;

  • Подготовка шаблона для загрузки в систему (удаление лишних вкладок в книге, форматирование таблицы, проверка введенных данных на корректность);

  • Проверка на соответствие с данными в нормативно-технической документации (НТД).

Шаблон для загрузки
Шаблон для загрузки

Для унификации материалов нашими специалистами был создан файл примеров ранее заведенных материалов, который хранится в облачном хранилище.

Файл примеров
Файл примеров

Рутина заключается в том, что файл приходилось постоянно открывать, копировать данные, искать материалы, а кто-то и вовсе мог на облаке удалить пример наименования материала.

Так как файл хранится в облачном хранилище, почему бы не подгружать данные из файла примеров прямо в сам шаблон для загрузки?  Для этого воспользуемся силой Power Query.

Для начала создадим ещё один лист в шаблоне под названием «Примеры».

На вкладке «Данные» нажимаем «Получить данные». Далее «Из других источников» и финальный аккорд «Из интернета».

Прошу обратить внимание, что конечный путь на файл заканчивается только форматом самого файла «.xlsx». При наличии параметра в ссылке на файл «?web=1» его следует удалить.

После ввода ссылки на файл появится окно Power Query, где мы жмем на кнопку «Загрузить». И вот уже появляются подгруженные данные из облачного хранилища.

В свойствах запроса листа «Примеры» советую поставить галочку на «Обновление при открытии файла». Также можно обновлять данные с заданным Вам диапазоном времени. В моем случае достаточно каждых 60 минут.

И вот самое интересное: по итогу мы получаем лист в шаблоне, который имеет актуальные данные. В шаблоне на вкладке «Данные» находим кнопку «Проверка данных» и выбираем необходимый столбец с наименованиями листа «Примеры».

Обязательно на ракурсе «Сообщение об ошибке» убрать галочку «Выводить сообщение об ошибке», чтобы можно было редактировать наименование примера.

Результат

Мы получаем перечень материалов в выпадающем списке, который можно редактировать, но самое удобное – искать материалы можно в самой ячейке. А сам файл примеров теперь защищен паролем и редактирует его только один человек, который и вносит актуальные данные.

Подготовка шаблона к импорту в систему

Суть рутины заключается в том, что необходимо каждый раз в Excel:

  1. Удалять ненужные листы при импорте шаблона;

  2. Сохранять шаблон в формате «.xlsx»;

  3. Переводить введенные данные в формат «умной» таблицы;

  4. Удалять комментарии, внесенные во время работы в шаблоне;

  5. Проверять на корректность введенных данных (Лишние пробелы в наименовании элементов, проставлены ли обязательные условия для импорта: количество элементов, единица измерения, подкласс и др).

Решить данную проблему помог VBA, который одним нажатием решает все 5 задач, указанных выше. Далее указан конечный вариант и шаблон, заполненные специально с «косяками».

Из рисунка видно, что пропущено количество элементов в столбце «E» и единица измерения в столбце «F». После нажатия на макрос появится окно с предупреждением.

В случае ошибок пропущенных значений также появится окно с предупреждением

Как видим, макрос удалил ненужные нам комментарии напротив фланцев, лишние вкладки и выделил те ячейки, которые необходимо заполнить. Также определил последнюю заполненную ячейку и по ней форматировал введенные данные в «умную» таблицу.

Немного кода

В качестве примера приведу функцию, которая во время сохранения шаблона проверяет незаполненные ячейки в столбце «Е», написанные для классов «99_00_Элементы спецификаций». Остальные функции схожи по написанию синтаксиса кода.

Function checkColumnE() 

Dim checkMsg As Boolean
checkMsg = False
Set ws = ThisWorkbook.Sheets("Шаблон")

lastRow = ws.Cells(Rows.Count, 7).End(xlUp).Row
Set rng = ws.range("G2:G" & lastRow)

For Each cell In rng.Cells
        If cell.Value = "99_00_Элементы спецификаций" And cell.Offset(0, -2).Value = "" Then
            If checkMsg = False Then
                checkMsg = True
                MsgBox "Заполни пустые ячейки в столбце E!"
            End If
            cell.Offset(0, -2).Interior.Color = RGB(250, 100, 100)
        End If
    Next cell

End Function

Доверяй, но проверяй

Каждый день специалист НСИ работает с НТД, проводит сверку значений (например, размеров деталей) в документации заказчика с указанными в ней стандартами. 

Невозможно запомнить все НТД. Для этого каждый раз приходится открывать ГОСТы и сверять значения, а под конец рабочего дня глаз может «замылиться», и можно допустить довольно глупую ошибку.

Макрос «Проверить_НТД» работает следующим образом: проверяет, находится ли в столбце «D» необходимый нам ГОСТ, к примеру, пусть это будет ГОСТ 8732-78, в случае нахождения значения, в столбец «С» напротив проверяемого элемента указывается комментарий о совпадении или о том, что по данному ГОСТу изготовление отсутствует, также предусмотрен вариант того, что данного размера и вовсе нет в НТД.

Также наглядно видно, как теперь при использовании вышеописанного макроса «Сохранить шаблон», он просто удалит все ненужные нам комментарии при подготовке шаблона к загрузке.

Сам код:

Покажу работу кода на примере тех же самых труб по ГОСТ 8732–78.

В нашем шаблоне на листе «Доп.сведения» скопирована таблица из открытых источников с размерами труб по ГОСТ 8732-78.

Чуть дальше по коду будет ещё один пример того, что использование функции значительно облегчает работу.

Функция CheckPipes принимает на вход 3 параметра: диапазон проверки Dn (диамтер), S (толщина) трубы и имя НТД.

Private Function CheckPipes(ByVal rngDn As range, rngS As range, ntd As String)

Dim ws As Worksheet
Dim Arr As Variant
Dim dn1Arr, s1Arr As Variant

Dim rng As range
Dim workRng As range
Dim lastRow As Long

Dim dnOffset As String
Dim sOffset As String

Dim x As range 'Второй цикл

On Error Resume Next

Set workRng = Application.Selection
Set ws = ThisWorkbook.Sheets("Допсведения")

dnOffset = WorksheetFunction.Count(rngDN)
sOffset = WorksheetFunction.Count(rngS)

Dim result As range

lastRow = ThisWorkbook.Sheets("Шаблон").Cells(Rows.Count, 4).End(xlUp).Row
Set rng = ThisWorkbook.Sheets("Шаблон").range("D2:D" & lastRow)

For Each cell In rng

'ntd - Поиск НТД в спеке
If InStr(cell, ntd) Then

Dim dn, dn1 As String
Dim s, s1 As String

'Массив преобразует "," в ".", поэтому используем Replace
    
        Arr = VBA.Split(Numbers(cell.Value), "х")
        dn1Arr = Str(Arr(0)) 'Ду
        s1Arr = Str(Arr(1)) 'Ру
        
        dn1Arr = Replace(dn1Arr, ".", ",")
        s1Arr = Replace(s1Arr, ".", ",")
        
        dn1Arr = Trim(dn1Arr)
        s1Arr = Trim(s1Arr)
        
Dim dnNum, sNum As Double

        dnNum = CDbl(dn1Arr)
        sNum = CDbl(s1Arr)

Далее определяем последнюю использованную ячейку в столбце «D» для нахождения проверяемого НТД. Если переменная совпадает, то в массив данных Arr присваиваются разбитые значения, но для этого пришлось написать ещё одну функцию «Numbers», которая извлекает из текста только числа и разделяет их символом «х».

В массив под индексом «0» присвоено значение Dn трубы, а под индексом «1» толщина стенки трубы.

Так как при присваивании значений переменных «Dn1Arr» и «S1Arr» типа Variant «,» меняется на «.», и добавляется лишний пробел. Используем метод Replace и Trim чтобы избавиться от ненужных символов.

А далее всё просто: пробегаемся при помощи цикла по проверяемому диапазону и при совпадении «Dn» и «S» из таблицы используем метод Intersect, который возвращает значение при пересечении двух диапазонов.

        For Each x In rngDN
            If x.Value = dnNum Then
                dn = x.Address & ":" & x.Offset(0, sOffset).Address
                dn1 = x.Value
            End If
        Next x

        For Each x In rngS
            If x.Value = sNum Then
                s = x.Address & ":" & x.Offset(dnOffset, 0).Address
                s1 = x.Value
            End If
        Next x
        
        If dnNum = dn1 And sNum = s1 Then
            Set result = Application.Intersect(ws.range(dn), ws.range(s))
            Trim (result)
        End If
        
        If result Is Nothing Then
            cell.Offset(0, -1).Font.Color = RGB(150, 0, 0)
            cell.Offset(0, -1).Value = "По ГОСТ отсутствует указанный размер"
        ElseIf result.Value = "-" Then
            cell.Offset(0, -1).Font.Color = RGB(150, 0, 0)
            cell.Offset(0, -1).Value = "По ГОСТ не изготовливают"
        Else
            cell.Offset(0, -1).Font.Color = RGB(0, 150, 60)
            cell.Offset(0, -1).Value = "Данные размеры совпадают с НТД"
        End If
    End If
    
   Set result = Nothing
    
Next

End Function

И вот, самое главное для тех, кто дочитал...

Как использование функций в макросах упрощает код в дальнейшем?

Мы видим, ниже в макросе нам остается самое простое – присвоить диапазон проверки для переменных и указать в параметрах функции сам НТД.

Sub J__Проверить_ГОСТ()

Dim ws As Worksheet
Dim rngDn1 As range 
Dim rngS1 As range 
Dim range As range

Set ws = ThisWorkbook.Sheets("Допсведения")

'ГОСТ 8732-78
Set rngDn1 = ws.range("G139:G208")
Set rngS1 = ws.range("H138:BF138")
Call CheckPipes(rngDn1, rngS1, "ГОСТ 8732-78")

'ГОСТ 8734-75
Set rngDn1 = ws.range("G224:G294")
Set rngS1 = ws.range("H223:AT223")
Call CheckPipes(rngDn1, rngS1, "ГОСТ 8734-75")

'ГОСТ 9940-81
Set rngDn1 = ws.range("BK170:BK194")
Set rngS1 = ws.range("BL169:CP169")
Call CheckPipes(rngDn1, rngS1, "ГОСТ 9940-81")

'ГОСТ 9941-81
Set rngDn1 = ws.range("G304:G371")
Set rngS1 = ws.range("H303:AS303")
Call CheckPipes(rngDn1, rngS1, "ГОСТ 9941-81")

'ГОСТ 9941-2022
Set rngDn1 = ws.range("BH304:BH376")
Set rngS1 = ws.range("BI303:DC303")
Call CheckPipes(rngDn1, rngS1, "ГОСТ 9941-2022")

End Sub

Выводы

Зачем это всё вам?

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

Комментарии (18)


  1. AlmazVafin
    20.03.2024 11:06
    +3

    Спасибо! Надо заняться изучением VBA


    1. economist75
      20.03.2024 11:06

      А также очень похожим на него StarBasic из свободного офисного пакета LibreOffice. И Python до кучи, потому то он тоже есть в LibreOffice. Списки из статьи в LibreOffice можно универсально организовать в любом приложении - тексте, таблице, рисунке, презентации по нажатию Ctrl+Shift+F4, используя для фильтрации данных удобную прослойку из SQL-запросов. Все это работает десятилетиями и достаточно надёжно. PowerQuery - кандидат на удалённую блокировку #1, поскольку ассоциирован с пользователями. Хотя я не алармист, но тревожно...


      1. Megabyte88
        20.03.2024 11:06

        Недавно была новость, что и в Excel питона завезли.


        1. economist75
          20.03.2024 11:06

          Завезли, но ограниченно: в W10/11 c WSL и только в MSO 365. И намедни пообещали MSO 365 заблокировать для РФ. Впрочем, даже с MSO 2007 доступен Python c либами XLwings и PyXLL (это работает через COM, своеобразно, но работает).


    1. nicolas_d
      20.03.2024 11:06

      Разве что, только для себя. В корп секторе лицензий на Excel уже не будет, Microsoft блокирует целый ряд приложений и сервисов.



  1. MihailKomarov
    20.03.2024 11:06

    Для более лучшей читабельности можно чтобы функция, которая извлекает числа из текста разделяла символом "_", а не "х". Лучше ведь "128_8", чем "128х8". Хотя, этот не так важно


    1. ganzyukvolodya Автор
      20.03.2024 11:06

      Согласен, функция может пригодится и для работы в других макросах


  1. NikolYankovsky
    20.03.2024 11:06
    +2

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


  1. itGuevara
    20.03.2024 11:06

    1 Есть ли что-то простое, чтобы формы Excel формировались в html, т.е., обработка таблиц на VBA, но экранные формы не во внутреннем формате, а публикуются как html (включая ввод данных в форму для изменения значений ячеек таблица).

    js-библиотеки есть, но хотелось бы что-то готовое, что позволяло бы представить обычную форму excel (vba) в виде html-странички, примерно, как это в гугл-таблицах.

    2 Есть что-то готовое, типа (задача): есть три (много) справочника (таблички именованных объектов). Каждый объект одного справочника связан с объектом другого один ко многим. Хотелось бы выбрав один объект, увидеть с какими объектами каждого другого справочника он связан. При этом связь достаточно задать один раз: задали в справочнике 1 связь: А (объект справочника 1) - связан с Б (объект справочника 2) и при анализе связей из справочника 2, мы определим, что Б связано с А. Видимо связи между объектами разных справочников нужно задавать не в отдельном (каждом) справочнике, а где то отдельно?

    Пример: есть список (справочник) процессов, список типовых форм и список НД (нормативный документ). В каждом списке кроме имени объекта - еще поля его свойств. Выбрали справочник процессов, выбрали в нем нужный процесс и рядом в окне с именем "типовая форма" увидели все названия типовых форм (с их свойствами), привязанных к этому процессу. В соседнем окне аналогично выводятся все названия НД (с параметрами НД), которые привязаны к выбранному процессу. Может быть есть готовое красивое решение?

    Связи получаются парные, поэтому руками дублировать их не хотелось бы в каждом справочнике, т.е. связь: А-Б в справочнике 1, должна автоматом дублироваться в справочник 2: Б-А. Или какой-то иной подход. Т.к. связь один ко многим, то для указании связи придется делать какие-то ухищрения, типа строка с id через запятую - со всеми связями к этому объекту.


    1. starfair
      20.03.2024 11:06
      +3

      1.Зачем? HTML априори медленнее внутренней реализации. Я сейчас борюсь с таблицами в Р7, но даже там, при том что всё почти построено на JS+HTML на ядре Chromium,сама таблица рисуется бинарным кодом где то глубоко внутри и только выводится в канву. Поверьте, тот способ общения с таблицами что есть в Excel+VBA почти идеальный вариант любой работы с ними
      2.Вы что то пытаетесь разные задачи в одну запихать. Иерархические справочники (и объекты в целом) чаще всего крайне не удобны для табличных представлений, и наоборот. Не даром, умные люди очень давно разделили это всё, и в одну кучу не пихают (если что, я про визуальную составляющую GUI, а не про форматы хранения такого рода представлений). То что вы описывате для примера, можно реализовать даже на VBA, но это будет крайне глючное, и медленное решение, так как для подобного рода задач вам нужен инструмент типа Access, но никак не Excel.


    1. Surrogate
      20.03.2024 11:06

      чтобы формы Excel формировались в html, т.е., обработка таблиц на VBA, но экранные формы не во внутреннем формате, а публикуются как html (включая ввод данных в форму для изменения значений ячеек таблица).

      js-библиотеки есть, но хотелось бы что-то готовое, что позволяло бы представить обычную форму excel (vba) в виде html-странички, примерно, как это в гугл-таблицах.

      Однажды несколько лет назад посмотрел как сохраняются рабочии книги Excel в облаке mail.ru! Реально в html, границы таблиц черточками прорисованы!!! Совсем не как в гуглотаблицах… Лютая жесть!


      1. Mail_Support
        20.03.2024 11:06

        Здравствуйте. На данный момент у сервиса Облако Mail.ru реализован Мой Офис и документы на просмотр открываются как положено.


        1. ganzyukvolodya Автор
          20.03.2024 11:06
          +1

          Сомнительно, но окэй...


    1. economist75
      20.03.2024 11:06
      +2

      Это можно сделать на Python во фреймворке Streamlit на 20 строк кода, который все хранит в SQLite или в том что ещё быстрее. Только тут для VBA и Excel работы уже не будет - экосистема Python c Pandas умеет всё, включая генерацию Excel-файлов.

      Web нужен по существу, для доступа с любых устр-в по всему миру? Если нет - обратите внимание на LibreOffice: в нем Формы ввода формата odt можно просто разослать пользователям по LAN и все данные будут автоматически одновременно попадать в базу данных любого проф. формата. И да, это без Макросов вообще. Добавив макросы можно сделать всё остальное. Код на vba в LibreOffice на 80% работает без переделки.


      1. itGuevara
        20.03.2024 11:06

        Хотелось бы все же на Excel. Там целая экосистема, включая, например, связку с Visio (и автономная задача для Visio \ Word \ Outlook \ Project и др.). Плюс, все хорошо знают таблички Excel. Не хватает только к нему научиться web прикручивать, точнее штатные формы публиковать в html или как вариант рисовать аналогичные экранные формы, но в другом конструкторе, который уже дружит с web и понимает объектную модель Excel.


  1. dsapelnikov
    20.03.2024 11:06

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

    1. Макросы уже основательно заблокированы по умолчанию, придется показывать каждому, как их разрешить, особенно если документы лежат в сетевых директориях.

    2. Приготовьте хороший автобэкап, т.к. крашатся макросы во время разработки на раз-два, нередко приводя не неоткрываемым файлам.

    3. Excel + git - это боль. Бинарный формат, этим все сказано. Read-only дифы с помощью самописных/3rd-party тулов возможны, мержи скриптов - тоже (потратил порядка недели для написания питоновских скриптов для 3-way merge), полноценные мержи страниц и контролов - если знаете, то расскажите как. Работать параллельно над одним и тем же файлом используя git из-за этого практически невозможно.

    4. Одна из основных концептуальных проблем с экселем - слитые воедино логика (формулы и макросы) и данные (содержимое ячеек). Из-за этого невозможно просто починить макрос в одном файле и распространить эти изменения на все файлы, которые содержат копию этого макроса. Лично я решил эту проблему "проксированием" содержимого ячеек в JSON: при сохранении эксельника сохраняется не сам файл, а его содержимое перенаправляется в JSON. При открытии такого эксельника JSON автоматически загружается в ячейки. С таким подходом можно использовать один и тот же эксель файл для нескольких файлов проектов. Метод естественно имеет довольно много ограничений.


    1. ganzyukvolodya Автор
      20.03.2024 11:06

      Да, в том то и дело что коллеги жить не могут без экселя, т.к. вся основная их работа - в цифровизации документации. А я, а я просто увлекаюсь программированием, вот так и столкнулся с VBA, когда потребовалось автоматизировать рутину.

      С автобэкапом согласен на все 100. Был случай, когда при открытии файла макросы просто куда-то пропадали... Причем файл никак не был поврежден. Excel и git не пытался связать (Шаблон с макросами весит не особо много, поэтому все версии изменений храню на локальном и часть - на облачном), поэтому и подсказать тут не смогу.

      За JSON отдельное спасибо, не рассматривал даже его для таких целей.