Когда придет пора сдавать проект,
И страшный нормоконтролер тебя возьмет за жабры,
Ты сможешь после гордо заявить – «К КД, товарищи, претензий нет!»
«Как это нет???» - «Вот так. Я прочитал статью на Хабре!»
При выполнении проектов, в которых требуется разработка конструкторской документации соответствующей ГОСТам ЕСКД или СПДС, возникает много задач, связанных с ее корректным изготовлением. Часть этих задач связана с непосредственным оформлением документов – заполнением основных надписей, полей в форматных рамках документа. Другая часть задач связана с поддержанием связности информации в пределах комплекта документов - единство используемых децимальных номеров, названий изделий, используемых в тексте наименований и тому подобных вещей. Такие задачи можно решать по разному, но автоматизация, безусловно, облегчит жизнь разработчику.
В данной статье, я расскажу о своем подходе к автоматизации такой работы на примере документов Word. Этот же подход применим и к Visio и к AutoCAD и к любому продукту, в котором предусмотрена возможность использования Visual Basic for Application (VBA).
Представим себе такие входные условия для решения:
в составе документации должны быть документы по ГОСТ 2.102, в том числе текстовые, оформленные с учетом ГОСТ 2.105, схемы по ГОСТ 2.701 и, не дай бог, что-то еще строительное по ГОСТ 21.101. А из инструментов есть только стандартный Microsoft Office, Microsoft Visio, Autodesk AutoCAD (это если бог был немилостив) и собственное желание оформить все как можно быстрее, лучше и не затрачивая усилий (то есть, в наличии имеется продуктивная лень).
Лирическое отступление
В некоторых случаях, в компаниях внедряют тяжелые системы автоматизированного проектирования и управления проектной документацией. Но мой опыт показал, что, во-первых, такие системы не ориентированы на российские стандарты и без танцев с бубном сложно выдать то, что им реально соответствует. Во-вторых, они трудны в освоении. В-третьих дороги. Из наиболее понравившихся мне в свое время продуктов упомяну, пожалуй, продукты компании Аскон (Компас, Лоцман, …). Они наши ГОСТы вполне учитывают.
С точки зрения ЕСКД, один из важных моментов для разрабатываемых документов – это рамки и основная надпись. И наверняка, те кто оформляли их в Word сталкивались с тем, как может «плыть» форматирование, размещение шрифтов и так далее.
Шаг 1. Делаем шаблоны текстовых документов.
Для всех документов, которые требуются в комплекте документации, предварительно оформляем в Word шаблоны – с правильным форматированием и рамками. Рамки удобнее всего делать в режиме колонтитулов, потому что в этом случае они как и все остальное, размещенное в колонтитулах, не мешают работать с содержательной частью документа.

Заметим, что рамки разные – поэтому для них
 придется создать различные разделы. Описывать создание рамок и текстовых полей –
 здесь не буду. Это делается достаточно просто, хотя и муторно. Но это делается
 всего один раз. Дальше спокойно пользуемся.
Удобно сразу в шаблонах использовать обновляемые поля Word. В частности, содержание, номер страницы, общее количество страниц, текущая дата. Я занес их сразу в соответствующие поля основной надписи – Дата, Лист, Листов и в других местах, где возможно.
Шаг 2. Создаем переменные документа
Связный комплект документов должен иметь одинаковые коды, обозначения, наименования и прочие сведения, относящиеся к комплекту в целом. Как можно избежать рутины правки этих полей во всем комплекте и при этом избегать ошибок?
Я решил использовать для этого пользовательские поля Word. В ручном режиме вставка такого поля осуществляется через меню (ленту) Вставка\ Экспресс блоки\Поле\DocVariable. В режиме отображения кода поля, оно выглядит так:
{ DOCVARIABLE Test \* MERGEFORMAT }
Как правило, любой документ комплекта содержит ключевые фрагменты, которые должны повторяться как в пределах документа, так и в комплекте. Для таких фрагментов в шаблоне создаются соответствующие поля – переменные.
Допустим, сейчас это будет название системы «Кабельная система», название документа «Программа и методика…», фамилия разработчика, децимальный код, код документа. В общем случае, сюда может войти и большой фрагмент текста. Причем интересно, что этот фрагмент при множественных вставках будет иметь необходимый формат контекста, куда его вставляют.
Создав все требуемые нам переменные, расставляем по тексту и колонтитулам соответствующие им поля в необходимом количестве. Теперь при изменении значения переменной и обновлении полей документа соответствующие изменения произойдут и в его отображении.
Шаг 3. Создание инструмента работы с полями
Доступ к прямому редактированию созданных полей весьма неудобен, поэтому для этого разумно сделать вспомогательный компонент – диалоговое окно. В VBA есть для этого все необходимое.
Ключевые функции, которые будут полезны при работе с документом в режиме автоматизации такие:
- создание переменной; 
- удаление переменной; 
- изменение текста/значения переменной; 
- вставка переменной в документ 

Создание переменной выбранного типа при помощи VBA производится элементарно:
Sub AddVar(Name As String, Value As String)
    ActiveDocument.Variables(Name).Value = Value
End SubУдаление переменной осуществляется так, чтобы везде, где она ранее была использована вместо нее остался только содержательный статичный текст.
Private Sub CommandButton1_Click()
    If MsgBox("Удалить переменную" + ufdel.cbLocals.Value + "?", vbOKCancel) = vbOK Then
        FindVarInText ufdel.cbLocals.Value, "Преобразовать в текст"
        ActiveDocument.Variables(ufdel.cbLocals.Value).Delete
    End If
    
    ReloadVars
    ufdel.cbLocals.Text = ActiveDocument.Variables(1).Name
End SubПри этом поиск преременных ведется как в основном тексте, так и в колонтитулах всех его разделов:
Sub FindVarInText(varName As String, Action As String)
    FieldAction ActiveDocument.Fields, varName, Action
   
    For sec = 1 To ActiveDocument.Sections.Count
        For head = 1 To ActiveDocument.Sections(sec).Headers.Count
            FieldAction ActiveDocument.Sections(sec).Headers(head).Range.Fields, varName, Action
        Next
        
        For foot = 1 To ActiveDocument.Sections(sec).Footers.Count
            FieldAction ActiveDocument.Sections(sec).Footers(foot).Range.Fields, varName, Action
        Next
    Next
End SubОбновление полей при изменении переменной разработчиком документа производится автоматически после его изменения в диалоговом окне (если стоит соответствующая галочка).
Private Sub TextBox1_AfterUpdate()
    Dim varName As String
    Dim Action As String
    
    If Not CheckBox1.Value Then Exit Sub
    
    lStat.BackColor = &HC0C0FF
    lStat.Caption = "Обновляется файл переменных..."
    ufdel.Repaint
    
    xlAddVars ufdel.tbFileName
    
    lStat.BackColor = &HC0C0FF
    lStat.Caption = "Обновляется текст документа..."
    ufdel.Repaint
    
    varName = cbLocals.Text
    Action = "Обновить"
    
    FieldAction ActiveDocument.Fields, varName, Action
    
    lStat.BackColor = &HC0C0FF
    lStat.Caption = "Обновляются колонтитулы..."
    ufdel.Repaint
    
    For sec = 1 To ActiveDocument.Sections.Count
        For head = 1 To ActiveDocument.Sections(sec).Headers.Count
            FieldAction ActiveDocument.Sections(sec).Headers(head).Range.Fields, varName, Action
        Next
        
        For foot = 1 To ActiveDocument.Sections(sec).Footers.Count
            FieldAction ActiveDocument.Sections(sec).Footers(foot).Range.Fields, varName, Action
        Next
    Next
    
    lStat.BackColor = &H8000000F
    lStat.Caption = "Значение"
End SubЯ сознательно сделал окно «Обработка переменных» немодальным. При этом оказалось возможным реализовать такой сценарий обработки (любого) документа:
Открывается документ (или ранее созданный шаблон) и открывается окно «обработка переменных». Разработчик меняет значение ранее созданных в документе полей в диалоговом окне и непосредственно наблюдает корректное изменение текста на экране. По мере написания или вычитки текста, он принимает решение о необходимости повторного использования какого-либо фрагмента. Он выделяет его мышью и нажимает кнопку «создать» в диалоговом окне. При этом автоматически создается переменная и заменяет исходный фрагмент на соответствующее ей обновляемое поле. Он читает документ дальше и в случае необходимости вставляет в текст поля ранее созданных переменных. По окончании правки, разработчик проводит ревизию значений переменных и при необходимости корректирует их. После всего, документ выводится на печать с опцией «обновлять поля при печати», либо он нажимает комбинацию “Сtrl-A” + F9 для ручного обновления и просмотра финального результата на экране.
Собственно, на этом шаге мы уже имеем инструмент, который позволяет нам получить некоторые преимущества редактирования документа, а именно:
- Нам не требуется заботиться о корректности отображения оформительской части документа – линии рамок никуда не смещаются при редактировании, текст не пропадает, основная надпись на месте и не разъезжается. 
- Нам не требуется входить в режим редактирования каждого колонтитула для правки текста, который в них должен находиться. При этом, пропадает проблема «случайно пропавших» разрывов разделов и смещения этих разделов в документе. 
- Мы четко понимаем, какие термины, сокращения, коды используются в документе и у нас нет нужды их перекрестно перепроверять и редактировать. Они меняются централизованно. 
- Если документ типовой, то мы можем вообще производить его редактирование не листая его, а только открыв диалоговое окно, в котором редактируется значение объявленных переменных (которые, напомню, могут быть очень большими). 
Сейчас, мы уже получили достаточно много полезных бонусов. Но ведь лень человеческая безгранична и мы помним, что хотели автоматизировать работу не с документом, а с комплектом документов, но...
Если внимательно посмотреть на рисунок окна пользовательского диалога, приведенную выше в статье, то можно заметить там упоминание файла variables.xls, общих переменных, считывания и сохранения.
В следующей статье, я расскажу о том, как удалось организовать работу с комплектом разнородных документов при помощи вспомогательной базы Excel и как оказалось возможным делать комплекты документов вообще не открывая Word.
Комментарии (36)
 - diogen421204.02.2022 17:16+2- Лучи ненависти тому, кто придумал эти таблички использовать в курсовых и дипломных работах… Одна из самых бесполезных вещей, что я делал в своей жизни и навсегда впитало в меня ненависть к высшему образованию (наверное, какой-нибудь научный коммунизм был хуже, но его я не застал).  - biokin05.02.2022 19:53- Все эти рамки и форматки вызывают стойкую ассоциацию с решетками, заборами и полосой препятствий. Взгляд не сосредотачивается на содержимом и ищет куда бы убежать ;)  - Txanxs Автор06.02.2022 20:35+1- На производстве для КД - полезно и системно. - В ВУЗе для курсовых и дипломных - бред пьяного ежика. 
 
 
 - Goose-Iron04.02.2022 18:51- Вещь интересная, но обычно использование скриптов по умолчанию отключено и даже запрещено. - И да, забыли про ГОСТ Р ИСО/МЭК 26300-2010, да пока всё ещё не обязателен к исполнению, но все же. - Ещё напомню, что были внесены изменения в ГОСТ Р 7.0.97, откуда было удалено использование проприетарных шрифтов и рекомендовано использовать свободные.  - Txanxs Автор05.02.2022 00:52- Все это из другой области и не имеет отношения к ЕСКД.  - Serp9006.02.2022 20:24- В ЕСКД аналогичные требования к проприетарным шрифтам вводит ГОСТ Р 2.105-2019 см. пункт 5.5.1  - Txanxs Автор06.02.2022 20:29- Никто не утверждает, что обязательно использовать ГОСТовские шрифты. Это вообще мелочи жизни. ГОСТ 2.105 в 5.1.1 - рекомендует использовать "имеющиеся шрифты". Что вообще можно трактовать и как возможность использования какой нибудь "вязи арабской". Но мы же серьезные люди!! - Для технических документов, типа таблиц, схем - мне лично больше нравится ГОСТовский шрифт. Для текстовых РЭ и инструкций, обычно, применяю Times New Roman 14. - Это элементарно меняется в шаблоне и на работу макросов никак не влияет. - :) 
 
 
 
 - z0ic04.02.2022 22:02- Самое интересное, что как правило VBA рабоает с приложением через COM сервер, поэтому его легко заменить на Python или С#.  - Txanxs Автор05.02.2022 01:03- В принципе, да. - Однако, еще один плюс VBA в том, что если нажать волшебную кнопку "Запись макроса" и начать делать с документом всякую ерунду - во встроенной IDE появляется тело функции = текст программы, содержащей базу всех действий, которые мы хотим совершать над документом. Далее, ее остается только привести в порядок. И не надо запоминать всякие встроенные константы, методы и конструкции. - Это, на мой взгляд, ускоряет реализацию идей автоматизации документа. 
 
 - mnhunter8105.02.2022 13:55- А в LibreOffice draw можно сотворить нечто подобное? Пытался "записать макрос" и не смог.  - Txanxs Автор06.02.2022 20:21- Я не помню, есть ли там VBA. По моему, нет. Или не было раньше.  - LuchS-lynx07.02.2022 08:48- в LibeeOffice есть Бэйсик для макросов, но он далеко не на 100% соответствует VBA 
 
 
 - LuchS-lynx05.02.2022 15:29- А почему Вы решили заполнять документы MS Word из Word'а? Столкнувгись с этой же проблемой мне показалось более простым решением заполнять из Excel'а. Так же через макросы VBA, но там данные прокидываются через функционал закладок. Т.е. в Word'е встраиваются закладки, а макросом этим закладкам присваиваются данные из таблицы Excel. - Rem -= Открываем файл скопированного шаблона по новому пути и заполняем его=- Set Wapp = CreateObject("word.Application"): Wapp.Visible = False Set Wd = Wapp.Documents.Open(ИмяФайла) NameOfBookmark = arrСсылкиДанных(1) ContentOfBookmark = Worksheets("Данные для проекта").Cells(3, 3) On Error Resume Next UpdateBookmarks Wd, NameOfBookmark, ContentOfBookmark Dim ContentString As String For i = 4 To Кол_воЭл_овМассиваДанных Step 1 If Len(arrСсылкиДанных(i)) > 1 Then NameOfBookmark = arrСсылкиДанных(i) ContentString = CStr(Worksheets("БД для АОСР (2)").Cells(i, НомерСтолбца)) If ContentString = "-" Or ContentString = "0" Then ContentString = "" ContentOfBookmark = ContentString On Error Resume Next UpdateBookmarks Wd, NameOfBookmark, ContentOfBookmark End If Next i Rem -= Обновляем поля, что бы ссылки в документе Word так же обновились и приняли значение закладок, на которые ссылаются =- Wd.Fields.Update Rem -= Сохраняем и закрываем файл =- Wd.SaveAs Filename:=ИмяФайла, FileFormat:=wdFormatXMLDocument Wd.Close False: Set Wd = Nothing Sub UpdateBookmarks(ByRef Wd, ByVal NameOfBookmark As String, ByVal ContentOfBookmark As Variant) On Error Resume Next Dim oRng As Variant Dim oBm Set oBm = Wd.Bookmarks Set oRng = oBm(NameOfBookmark).Range oRng.Text = ContentOfBookmark oBm.Add NameOfBookmark, oRng End Sub - Txanxs Автор06.02.2022 20:18- В ворде работаем - в ворде заполняем. Эксель удобен, я дальше расскажу, когда документов много. А когда всего один - то лишний раз открывать эксель, а потом проверять, что все нормально импортировалось оттуда - это, мне кажется, дополнительная работа. - Но это только мое мнение. 
 
 - Dier_Sergio_Great06.02.2022 03:12- Лучше бы поддержку скриптов на JS бы сделали бы.  - Txanxs Автор06.02.2022 20:22- JuSt for fun?  - Dier_Sergio_Great07.02.2022 04:55- Для врачей разных народов, владение латынью обязательно. А для программистов разных языков программирования JS тоже обязательно, в общем просто приходится с ним иметь дело. А VB навязывание какое то. Например технологии IOT сейчас осваивают JS. Даже есть пословица: "Все что может быть написано на JS, обязательно будет написано!".  - starfair07.02.2022 09:29- Сомнительное утврждение, на мой взгляд. То что JS сейчас стал использоваться где надо, и где не надо, вовсе не осзначает, что его обязаны знать все, кто занимается программированием. Желательно, может быть. Но обязательно - это вряд ли. Впрочем, относится это вообще к любому популярному языку программирования, будь то Phyton, C++ или Java к примеру. Хорошему программисту скорее важнее правильно выбирать язык под задачу, нежели ставить костыли из разных ЯП, потому что так проще в текущий момент. Иле того хуже - чтобы демонстрировать свою сопричастность мэйнстримам. 
 
 
 
 - teqs06.02.2022 20:30- Честно почему нельзя в компасе сделать свои правила проверки основной надписи, оформления таблиц, размеров. Работа бы стала намного приятней  - LuchS-lynx07.02.2022 08:50- Кстати перспективная тема, дарю идею - передача текста макросом с привязками в файлы DWG/Компасс  - Txanxs Автор07.02.2022 13:21- А у меня есть связка с AutoCAD. Через атрибуты блоков.  - LuchS-lynx07.02.2022 13:23- где можно почитать об этом? не про вставку таблички, а про вставку/замену отдельных, заранее настроенных, что бы не слетало форматирование, блоков текста?  - Txanxs Автор07.02.2022 13:44- В автокаде?  - LuchS-lynx07.02.2022 13:45- да, как подтягивать текст в Автокад через макрос.  - Txanxs Автор07.02.2022 13:57+1- Поищу по сусекам. Если найду - опишу в следующей статье. (С автокадом давно не работал, архив надо посмотреть). - Про большие фрагменты текста - не помню точно, что там было у меня - но точно был такой подход: - Блоки основной надписи содержат атрибуты, имя которых соответствует названию переменной/поля, такое же, как содержится в том же ворде. Так как я хотел, чтобы распознавание полей автозаполнения в автокаде было автоматическим, то я при анализе блоков автокада принял умолчание - "если атрибут начинается с буквы "v" то это переменная, которую надо заполнять из внешнего источника, а именно Excel-файла, и все атрибуты с таким именем в любом блоке чертежа будут одинаковыми. Причем обрабатываются все блоки, как на вкладке Model, так и на всех вкладках Layout. 
- Табличные документы - каждая строка идет как один блок. Он заполняется через Excel-файл: выделяется набор имортируемых строк (с листа Excel - должно просто совпадать количество столбцов, форматирование не имеет значения) и после вызывается макрос, который лезет в Excel и по количеству выделенных строк создает блоки и в них помещает текст. 
- По текстовым документам - кажется аналогичный был подход, но с постраничным импортом из Word. 
 - Последние два пункта неактуальны, так как табличные документы переехали в Visio, а текстовые - в Word. - Т.е. для автокада актуально только заполнение основных надписей на чертежах, типа поэтажных планов.  - LuchS-lynx07.02.2022 14:05- Поищу по сусекам. Если найду - опишу в следующей статье. (С автокадом давно не работал, архив надо посмотреть). - Буду благодарен =) благо тема сейчас актуальная. - Т.е. для автокада актуально только заполнение основных надписей на чертежах, типа поэтажных планов. - Вот тут не соглашусь, т.к. на однотипных чертежах/схемах, например на дефектах, здорово экономит время, когда у тебя рисунок один и тот же, а надписи разные. Потом никто же не запрещает чертить условные схемы линейных объектов с привязкой к проценту выполненных работ, при условии что мы привязаны к пикетам. Или же рисовать по отметкам профиль трубы и земляных масс. Опять же вывод подготовленных текстовых спецификаций. 
 Наверное проектировщику так нельзя относится к документам, но вот уже ПТОшнику - можно и даже нужно, т.к. все то, что сэкономит время должно экономить время - Txanxs Автор07.02.2022 15:46- Ну, я ориентировался на специфику проектирования инженерных систем (СКС, электрика - поэтажные планы) - По идее, подход с блоками позволяет любую информацию в любом виде связать с Ексель-источником. 
 
 
 
 
 
 
 
 
 
           
 
dvserg
А профессиональные системы разработки КД не используете?
Txanxs Автор
Профильные подразделения - используют. Для задач масштаба предприятия.